Check it out...
Oracle ADF is a powerful application framework for building next generation enterprise applications. This blog discusses some interesting use case scenarios and solutions using ADF and the underlying Java EE technologies.
The views expressed on this blog are my own and do not necessarily reflect the views of my employer.
Friday, July 29, 2011
Thursday, July 28, 2011
Clearing the stale messages from the previous request on client side validation error
While going through a specific use case, I came to know that ADF Faces run time does not auto clear the messages added to the page from the previous request. This indeed is the expected behavior as of now. I'm sure many of you know this already, however thought of posting this for the benefit of developers who has not worked on such scenarios before, like me;).
The side effect of this implementation is that, once you displayed any message to the end user by adding a FeacesMessage to a FacesConetxt from an event handler method and if the next immediadte action from the end user result in anay client side validation error, you may get the previous message and the newly generated validation error in the message window as shown in the following screen shot.
Let me discuss a work around solution for such use cases. Its simple, add a af:clientListener to the UI component to clear the messages by calling ADF Fcaes JavaScript API AdfPage.PAGE.clearMessages(componentId);.
Download
I'm attaching a very simple example illustrating the above solution. You can download the sample workspace from here.
[Built using Oracle JDeveloper 11.1.2.0.0]
How to run this sample?
Run test.jspx, key in some values in the input field and click save button. You may see information message. If you click save button again, validation error message alone appears.The previous INFO message is cleared using javascript method clearGlobalMessage()
Please note that, the above case will be addressed in future releases in a much better way. In fact there is an enhancement request for the same, be happy :)
The side effect of this implementation is that, once you displayed any message to the end user by adding a FeacesMessage to a FacesConetxt from an event handler method and if the next immediadte action from the end user result in anay client side validation error, you may get the previous message and the newly generated validation error in the message window as shown in the following screen shot.
Let me discuss a work around solution for such use cases. Its simple, add a af:clientListener to the UI component to clear the messages by calling ADF Fcaes JavaScript API AdfPage.PAGE.clearMessages(componentId);.
<af:commandButton text="Save with Clearing Prev Message"
id="cb2" actionListener="#{TestBean.saveAction}"
partialSubmit="true">
<af:clientListener method="clearGlobalMessage" type="click"/>
</af:commandButton>
</af:form>
<af:resource type="javascript">
function clearGlobalMessage() {
AdfPage.PAGE.clearMessages(null);
}
</af:resource>
Download
I'm attaching a very simple example illustrating the above solution. You can download the sample workspace from here.
[Built using Oracle JDeveloper 11.1.2.0.0]
How to run this sample?
Run test.jspx, key in some values in the input field and click save button. You may see information message. If you click save button again, validation error message alone appears.The previous INFO message is cleared using javascript method clearGlobalMessage()
Please note that, the above case will be addressed in future releases in a much better way. In fact there is an enhancement request for the same, be happy :)
Sunday, July 24, 2011
Tips on using oracle.jbo.domain.Array as NamedWhereClauseParam value
Sometime back I've blogged on Using oracle.jbo.domain.Array with ViewCriteria. Let me revisit the same topic with slightly different usage. There are many use cases where oracle.jbo.domain.Array is used as a NamedWhereClauseParam value, ViewObjectImpl::setNamedWhereClauseParam(name,value). If you have such use cases and at run time you hit the following exception, then this blog post is for you ;)
oracle.jbo.JboException: Cannot insert/update Array without context information at oracle.jbo.domain.Array.prepareForDML(Array.java:773) at oracle.jbo.server.ViewRowSetImpl.prepareLobObjectForBind(ViewRowSetImpl.java:8154) at oracle.jbo.server.ViewRowSetImpl.getParametersAsStorageTypes(ViewRowSetImpl.java:5004) at oracle.jbo.server.ViewRowSetImpl.getParametersAsStorageTypes(ViewRowSetImpl.java:4979) at
Solution
If you define bind variable at design time, you may need to key in ColumnType(db object to hold Array that you are passing) as well along with other attributes. Please see my previous post if you are not aware of this part. All works well in this case. When you use ViewObjectImpl::defineNamedWhereClauseParam(...) to define bind variable for Array at run time, the definition is missing this entry and you may hit the above said error. The solution is to set the required context while creating oracle.jbo.domain.Array as shown in the following code snippet.
I'm copying the relevant code below for your reference.
oracle.jbo.JboException: Cannot insert/update Array without context information at oracle.jbo.domain.Array.prepareForDML(Array.java:773) at oracle.jbo.server.ViewRowSetImpl.prepareLobObjectForBind(ViewRowSetImpl.java:8154) at oracle.jbo.server.ViewRowSetImpl.getParametersAsStorageTypes(ViewRowSetImpl.java:5004) at oracle.jbo.server.ViewRowSetImpl.getParametersAsStorageTypes(ViewRowSetImpl.java:4979) at
Solution
If you define bind variable at design time, you may need to key in ColumnType(db object to hold Array that you are passing) as well along with other attributes. Please see my previous post if you are not aware of this part. All works well in this case. When you use ViewObjectImpl::defineNamedWhereClauseParam(...) to define bind variable for Array at run time, the definition is missing this entry and you may hit the above said error. The solution is to set the required context while creating oracle.jbo.domain.Array as shown in the following code snippet.
String[] deptArray = { "Administration","Purchasing" };
Array arr = new Array(deptArray);
HashMap context = new HashMap();
context.put(DomainContext.ELEMENT_SQL_NAME, "CHARTABLETYPE");
context.put(DomainContext.ELEMENT_TYPE, String.class);
arr.setContext(null, null, context);
I'm copying the relevant code below for your reference.
public void findDepartmentsForArrayParam() {
ViewObjectImpl deptVOImpl = getDepartmentsView1();
deptVOImpl.defineNamedWhereClauseParam("ArrayOfDeptNames", null,
null);
deptVOImpl.setWhereClause("Departments.DEPARTMENT_NAME
IN (SELECT * FROM TABLE(CAST(:ArrayOfDeptNames AS CHARTABLETYPE)))");
deptVOImpl.setNamedWhereClauseParam("ArrayOfDeptNames",
getValueAsArray());
deptVOImpl.executeQuery();
}
public Array getValueAsArray() {
Array arr = null;
try {
String[] deptArray = { "Administration","Purchasing" };
arr = new Array(deptArray);
HashMap context = new HashMap();
context.put(DomainContext.ELEMENT_SQL_NAME, "CHARTABLETYPE");
//CHARTABLETYPE is DB object
//CREATE OR REPLACE TYPE "CHARTABLETYPE" as table of varchar2(4000);
context.put(DomainContext.ELEMENT_TYPE, String.class);
arr.setContext(null, null, context);
} catch (Exception ex) {
ex.printStackTrace();
}
return arr;
}
Tips on using oracle.jbo.domain.Array as a NamedWhereClauseParam value
Sometime back I've blogged on Using oracle.jbo.domain.Array with ViewCriteria. Let me revisit the same topic with slightly different usage. There are many use cases where oracle.jbo.domain.Array is used as a NamedWhereClauseParam value, ViewObjectImpl::setNamedWhereClauseParam(name,value). If you have such use cases and at run time you hit the following exception, then this blog post is for you ;)
oracle.jbo.JboException: Cannot insert/update Array without context information at oracle.jbo.domain.Array.prepareForDML(Array.java:773) at oracle.jbo.server.ViewRowSetImpl.prepareLobObjectForBind(ViewRowSetImpl.java:8154) at oracle.jbo.server.ViewRowSetImpl.getParametersAsStorageTypes(ViewRowSetImpl.java:5004) at oracle.jbo.server.ViewRowSetImpl.getParametersAsStorageTypes(ViewRowSetImpl.java:4979) at
Solution
If you define bind variable at design time, you may need to key in ColumnType(db object to hold Array that you are passing) as well along with other attributes. Please see my previous post if you are not aware of this part. All works well in this case. When you use ViewObjectImpl::defineNamedWhereClauseParam(...) to define bind variable for Array at run time, the definition is missing this entry and you may hit the above said error. The solution is to set the required context while creating oracle.jbo.domain.Array as shown in the following code snippet.
I'm copying the relevant code below for your reference.
oracle.jbo.JboException: Cannot insert/update Array without context information at oracle.jbo.domain.Array.prepareForDML(Array.java:773) at oracle.jbo.server.ViewRowSetImpl.prepareLobObjectForBind(ViewRowSetImpl.java:8154) at oracle.jbo.server.ViewRowSetImpl.getParametersAsStorageTypes(ViewRowSetImpl.java:5004) at oracle.jbo.server.ViewRowSetImpl.getParametersAsStorageTypes(ViewRowSetImpl.java:4979) at
Solution
If you define bind variable at design time, you may need to key in ColumnType(db object to hold Array that you are passing) as well along with other attributes. Please see my previous post if you are not aware of this part. All works well in this case. When you use ViewObjectImpl::defineNamedWhereClauseParam(...) to define bind variable for Array at run time, the definition is missing this entry and you may hit the above said error. The solution is to set the required context while creating oracle.jbo.domain.Array as shown in the following code snippet.
String[] deptArray = { "Administration","Purchasing" };
Array arr = new Array(deptArray);
HashMap context = new HashMap();
context.put(DomainContext.ELEMENT_SQL_NAME, "CHARTABLETYPE");
context.put(DomainContext.ELEMENT_TYPE, String.class);
arr.setContext(null, null, context);
I'm copying the relevant code below for your reference.
public void findDepartmentsForArrayParam() {
ViewObjectImpl deptVOImpl = getDepartmentsView1();
deptVOImpl.defineNamedWhereClauseParam("ArrayOfDeptNames", null,
null);
deptVOImpl.setWhereClause("Departments.DEPARTMENT_NAME
IN (SELECT * FROM TABLE(CAST(:ArrayOfDeptNames AS CHARTABLETYPE)))");
deptVOImpl.setNamedWhereClauseParam("ArrayOfDeptNames",
getValueAsArray());
deptVOImpl.executeQuery();
}
public Array getValueAsArray() {
Array arr = null;
try {
String[] deptArray = { "Administration","Purchasing" };
arr = new Array(deptArray);
HashMap context = new HashMap();
context.put(DomainContext.ELEMENT_SQL_NAME, "CHARTABLETYPE");
//CHARTABLETYPE is DB object
//CREATE OR REPLACE TYPE "CHARTABLETYPE" as table of varchar2(4000);
context.put(DomainContext.ELEMENT_TYPE, String.class);
arr.setContext(null, null, context);
} catch (Exception ex) {
ex.printStackTrace();
}
return arr;
}
Wednesday, July 20, 2011
Tips on using af:media to display OrdImage
When you use af:media to display OrdImage type though ADF binding, you are expected to help the binding layer by mentioning the special treatment requirement for the source attribute. Failing to do may result in the following error ;)
Solution is simple, open the page definition and key in CustomInputHandler="OrdDomainValueHandler" for the attribute which is bound to OrdDomain type. The OrdDomainValueHandler class serves as the custom handler for intermedia objects. Note that af:media will use the OrdDomainValueHandler to extract values for specific attributes( source, innerHeight, innerWidth etc. ) which can't be read directly from the associated ViewObject.
Example:
javax.el.PropertyNotFoundException: The class 'oracle.ord.im.OrdImageDomain' does not have the property 'media'
Solution is simple, open the page definition and key in CustomInputHandler="OrdDomainValueHandler" for the attribute which is bound to OrdDomain type. The OrdDomainValueHandler class serves as the custom handler for intermedia objects. Note that af:media will use the OrdDomainValueHandler to extract values for specific attributes( source, innerHeight, innerWidth etc. ) which can't be read directly from the associated ViewObject.
Example:
JSF tag:
<af:media source="#{bindings.Image.inputValue.source}"
contentType="#{bindings.Image.inputValue.media.mimeType}" id="ot1"/>
Page definition entry:
<attributeValues IterBinding="ImageView1Iterator"
id="Image" CustomInputHandler="OrdDomainValueHandler">
<AttrNames>
<Item Value="Image"/>
</AttrNames>
</attributeValues>
Friday, July 15, 2011
UI Categories...What is that?
Well...If you worked on JDeveloper 11.1.2.0.0 release, you might have noticed UI Categories option in View Object editor. This is a useful to group/order the view object attributes, and will be used by the components like af:query, dynamic:form etc in future releases. Please be patient and getting ready for some new things arriving soon!
You can learn more from fusion developers guide - 5.13.3 How to Define UI Category Hints.
You can learn more from fusion developers guide - 5.13.3 How to Define UI Category Hints.
Tips on using showPrintablePageBehavior with af:table
You can use <af:showPrintablePageBehavior> tag with command components to display printable view of the pages. The usage is detailed in Web UI Developers Guide - 34 Using Different Output Modes
Please note the printable page produced by af:showPrintablePageBehavior is really meant for printing ;) - this page is very light weight and might be missing java script support. You may need to give special attention to this point if you want to build a printable view of a af:table with stretchable behavior( table with columnStretching="multiple"). ADF Faces run time stretches the table columns using client side java script. Apparently the printable view of such tables might not be aligned properly as the java script magic is missing. A possible solution is to conditionally set width for the columns based on the OutputMode(email,printable etc.). The same logic can be used for hiding specific components from the printable view.
The below given code snippet may help you to understand this better. In the following example column width is set as 50% in normal mode, which is required to enable the stretchable behavior for table. In email/printable mode width is set in fixed pixels - 300
<af:column sortProperty="#{bindings.DepartmentsView1.hints.DepartmentName.name}"
headerText="#{bindings.DepartmentsView1.hints.DepartmentName.label}" id="c2"
width="#{adfFacesContext.outputMode eq 'email' or adfFacesContext.outputMode eq 'printable' ? '300' : '50%'}">
<af:outputText value="#{row.DepartmentName}" id="ot2"/>
</af:column>
Your 'printable' table source may look like as given below,
Please note the printable page produced by af:showPrintablePageBehavior is really meant for printing ;) - this page is very light weight and might be missing java script support. You may need to give special attention to this point if you want to build a printable view of a af:table with stretchable behavior( table with columnStretching="multiple"). ADF Faces run time stretches the table columns using client side java script. Apparently the printable view of such tables might not be aligned properly as the java script magic is missing. A possible solution is to conditionally set width for the columns based on the OutputMode(email,printable etc.). The same logic can be used for hiding specific components from the printable view.
The below given code snippet may help you to understand this better. In the following example column width is set as 50% in normal mode, which is required to enable the stretchable behavior for table. In email/printable mode width is set in fixed pixels - 300
<af:column sortProperty="#{bindings.DepartmentsView1.hints.DepartmentName.name}"
headerText="#{bindings.DepartmentsView1.hints.DepartmentName.label}" id="c2"
width="#{adfFacesContext.outputMode eq 'email' or adfFacesContext.outputMode eq 'printable' ? '300' : '50%'}">
<af:outputText value="#{row.DepartmentName}" id="ot2"/>
</af:column>
Your 'printable' table source may look like as given below,
<af:table ...
rowSelection="single" id="t1" columnStretching="multiple">
<af:column sortProperty="#{bindings.DepartmentsView1.hints.DepartmentName.name}"
headerText="#{bindings.DepartmentsView1.hints.DepartmentName.label}" id="c2"
width="#{adfFacesContext.outputMode eq 'email' or adfFacesContext.outputMode eq 'printable' ? 300 : '50%'}">
<af:outputText value="#{row.DepartmentName}" id="ot2"/>
</af:column>
<af:column sortProperty="#{bindings.DepartmentsView1.hints.ManagerId.name}"
headerText="#{bindings.DepartmentsView1.hints.ManagerId.label}" id="c3"
width="#{adfFacesContext.outputMode eq 'email' or adfFacesContext.outputMode eq 'printable' ? '100' : '25%'}">
<af:outputText value="#{row.ManagerId}" id="ot3">
<af:convertNumber groupingUsed="false"
pattern="#{bindings.DepartmentsView1.hints.ManagerId.format}"/>
</af:outputText>
</af:column>
<af:column sortProperty="#{bindings.DepartmentsView1.hints.LocationId.name}"
headerText="#{bindings.DepartmentsView1.hints.LocationId.label}" id="c4"
width="#{adfFacesContext.outputMode eq 'email' or adfFacesContext.outputMode eq 'printable' ? '100' : '25%'}">
<af:outputText value="#{row.LocationId}" id="ot4">
<af:convertNumber groupingUsed="false"
pattern="#{bindings.DepartmentsView1.hints.LocationId.format}"/>
</af:outputText>
</af:column>
</af:table>
Friday, July 8, 2011
JDK 7 Features
Check it out - JDK 7 Features
I should say (along with many others) API Doc looks much better now ;) - http://download.java.net/jdk7/docs/api/
I should say (along with many others) API Doc looks much better now ;) - http://download.java.net/jdk7/docs/api/
Changing the default display of af:quickQuery using criteriaItems facet
Is there a way to change the default display of search items used in an af:quickQuery component?
Well answer is Yes. If you want to change the default display of <af:quickQuery> component you can do that by adding your own component set inside criteriaItems facet. Please check out the tag doc for <af:quickQuery> to learn more.
The below shown example may alter the quickQuery component display showing af:outputLabel for the search criteria item instead of the default drop down list. This specific example is useful when you have only one field in the the view object (a rare scenario though). Thanks to Sriram Raghavan(Oracle - ADF team) who shared this tip in an internal discussion forum :)
You can see the difference in display in the following picture. The first quickQuery displays search criteria item(s) using a drop down( which is default), whereas the second one displays the search criteria item on a label.
Well answer is Yes. If you want to change the default display of <af:quickQuery> component you can do that by adding your own component set inside criteriaItems facet. Please check out the tag doc for <af:quickQuery> to learn more.
The below shown example may alter the quickQuery component display showing af:outputLabel for the search criteria item instead of the default drop down list. This specific example is useful when you have only one field in the the view object (a rare scenario though). Thanks to Sriram Raghavan(Oracle - ADF team) who shared this tip in an internal discussion forum :)
<af:quickQuery label="Search" searchDesc="Search" id="qryId1"
value="#{bindings.ImplicitViewCriteriaQuery.quickQueryDescriptor}"
model="#{bindings.ImplicitViewCriteriaQuery.queryModel}"
queryListener="#{bindings.ImplicitViewCriteriaQuery.processQuery}">
<f:facet name="end">
<af:commandLink text="Advanced" rendered="true" id="cl1"/>
</f:facet>
<f:facet name="criteriaItems">
<af:outputLabel
value="#{bindings.ImplicitViewCriteriaQuery.quickQueryDescriptor.currentCriterion.attribute.label}"
shortDesc="#{bindings.ImplicitViewCriteriaQuery.quickQueryDescriptor.currentCriterion.attribute.description}"/>
</f:facet>
</af:quickQuery>
You can see the difference in display in the following picture. The first quickQuery displays search criteria item(s) using a drop down( which is default), whereas the second one displays the search criteria item on a label.
Thursday, July 7, 2011
What you may need to know about the conditional activation of the task flow embedded in an <af:popup> ?
You can configure the activation of task flow using 'active' property of the taskFlow binding. The details are available in the fusion developers guide - 21.6 Configuring Activation of an ADF Region
I would like to share a couple of points I learned on this topic while working with developers. Its interesting and may save your time as well ;)
While configuring the activation of task flow, you may need to key in value for activation and active flags. Apart from these two, there is one more attribute RefreshCondition which decides the 'life' of task flow.
Common mistakes in using RefreshCondition and active properties
RefreshCondition="#{some.EL.expression}": The ADF region is refreshed when RefreshCondition evaluates true. Please note that you may not really need to use this for lazy initialization of task flow, use active and activation flags instead. In case, if you are using this, please note the RefreshCondition should only evaluate to true when you want the
task flow to start/restart. You may need to make your EL to return false once task flow is active. Failing to do so will cause task flow to reset/restart for each post back. A typical usage of this flag may be, restart the task flow while the region is active. Here you need to ensure the RefreshCondition evaluates to true when you want the task flow to restart and false at all other times.
activation: Though you can specify values like conditional/deferred/active for this flag, in this post I discuss conditional activation. Setting activation=conditional, activates the ADF region if the EL expression set as a value for the task flow binding 'active' property(discussed below) returns true.
active="#{some.EL.expression}": This is the area where you may need to be careful. If the activation is set as conditional, the the EL for active property must evaluate to true for each postback for the region to remain active. This implies that the scope where you keep the active flag should be long enough to survive multiple requests from the client while working on task flow.
Let me explain this with a simple example. Assume that you built a task flow and wanted to display in an af:popup. Apparently you might not want to activate the task flow till user opts to view the pop up dialog. You may end up in using active flag to control the activation of task flow. Consider an EL as shown below for the active flag.
active="#{empty requestScope.activeFlag ? false : requestScope.activeFlag}"
What is wrong with this?
Well, its syntactically valid, however may not help you to achieve the desired functionality. Because whatever you store in requestScope is valid for that specific request. Consider your task flow popup dialog is displayed with the above 'active' settings. All went well so far. Then user does some action which may trigger some server interaction. While posting back to server, run time will evaluate active EL before processing task flow. Whatever you set to the requestScope in the previous request may not be available for the new request and EL will be evaluated to false, and your task flow dialog may appear as frozen.
What is the solution?
You may need to keep the activation flag in higher scopes - pageFlowScope or sessionScope. Better one may be pageFlowScope. (Please note that dialog window may not be able to access view scope of the parent view, so we don't use view scope in this specific context)
active="#{empty pageFlowScope.activeFlag ? false : pageFlowScope.activeFlag}"
Download
You can download the example workspace from here.
[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2) + HR Schema]
A glance at the implementation
This example uses employee-task-flow which is displayed inside popup dialog. The activation of the task flow is controlled using active="#{empty pageFlowScope.activeFlag ? false : pageFlowScope.activeFlag}" for <taskFlow> binding. The activeFlag is set true from the popupFetchListener method defined in the MainBean class.
Learn More ...
There are a lot more points like this. If you are curious to learn the internals of the ADF Business Components and ADF Binding Layer, the following book is for you - Oracle ADF Real World Developer’s Guide.
More details about this book can be found in this post- http://jobinesh.blogspot.in/2012/07/pre-order-your-copy-of-oracle-adf-real.html
I would like to share a couple of points I learned on this topic while working with developers. Its interesting and may save your time as well ;)
While configuring the activation of task flow, you may need to key in value for activation and active flags. Apart from these two, there is one more attribute RefreshCondition which decides the 'life' of task flow.
Common mistakes in using RefreshCondition and active properties
RefreshCondition="#{some.EL.expression}": The ADF region is refreshed when RefreshCondition evaluates true. Please note that you may not really need to use this for lazy initialization of task flow, use active and activation flags instead. In case, if you are using this, please note the RefreshCondition should only evaluate to true when you want the
task flow to start/restart. You may need to make your EL to return false once task flow is active. Failing to do so will cause task flow to reset/restart for each post back. A typical usage of this flag may be, restart the task flow while the region is active. Here you need to ensure the RefreshCondition evaluates to true when you want the task flow to restart and false at all other times.
activation: Though you can specify values like conditional/deferred/active for this flag, in this post I discuss conditional activation. Setting activation=conditional, activates the ADF region if the EL expression set as a value for the task flow binding 'active' property(discussed below) returns true.
active="#{some.EL.expression}": This is the area where you may need to be careful. If the activation is set as conditional, the the EL for active property must evaluate to true for each postback for the region to remain active. This implies that the scope where you keep the active flag should be long enough to survive multiple requests from the client while working on task flow.
Let me explain this with a simple example. Assume that you built a task flow and wanted to display in an af:popup. Apparently you might not want to activate the task flow till user opts to view the pop up dialog. You may end up in using active flag to control the activation of task flow. Consider an EL as shown below for the active flag.
active="#{empty requestScope.activeFlag ? false : requestScope.activeFlag}"
What is wrong with this?
Well, its syntactically valid, however may not help you to achieve the desired functionality. Because whatever you store in requestScope is valid for that specific request. Consider your task flow popup dialog is displayed with the above 'active' settings. All went well so far. Then user does some action which may trigger some server interaction. While posting back to server, run time will evaluate active EL before processing task flow. Whatever you set to the requestScope in the previous request may not be available for the new request and EL will be evaluated to false, and your task flow dialog may appear as frozen.
What is the solution?
You may need to keep the activation flag in higher scopes - pageFlowScope or sessionScope. Better one may be pageFlowScope. (Please note that dialog window may not be able to access view scope of the parent view, so we don't use view scope in this specific context)
active="#{empty pageFlowScope.activeFlag ? false : pageFlowScope.activeFlag}"
Download
You can download the example workspace from here.
[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2) + HR Schema]
A glance at the implementation
This example uses employee-task-flow which is displayed inside popup dialog. The activation of the task flow is controlled using active="#{empty pageFlowScope.activeFlag ? false : pageFlowScope.activeFlag}" for <taskFlow> binding. The activeFlag is set true from the popupFetchListener method defined in the MainBean class.
Learn More ...
There are a lot more points like this. If you are curious to learn the internals of the ADF Business Components and ADF Binding Layer, the following book is for you - Oracle ADF Real World Developer’s Guide.
More details about this book can be found in this post- http://jobinesh.blogspot.in/2012/07/pre-order-your-copy-of-oracle-adf-real.html
Friday, July 1, 2011
Overriding <af:query> display at run time
Sometime back I posted similar post on the above topic - Customizing the af:query component display by overriding CriteriaItemAttributeHints
Its time for me to revisit the same topic with slightly different use case :)
The use case requirement was to override the ViewCrtieria hints of a base view object from a child view object. Well, its easy. You can hook your code by overriding ViewObjectImpl::getCriteriaItemAttributeHints(ViewCriteriaItem vci), and optionally return your own AttributeHints implementation. In the following code sample, I'm demonstrating this by changing some properties of a ViewCriteriaItem for specific items.
Before winding up today's post, let me teach you one more useful tip on the same context. An interesting enhancement available with 11.1.2.0.0 release is the ability specify 'Display Width' for each view criteria item while defining a view criteria. This property decides the width of the UI control (displayed inside the query component) at run time. Please note that in previous releases the af:query component was using display width from the view object's attribute definition (by default) to render controls.
Download
You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2) + HR Schema]
A glance at the implementation
This sample uses 2 view object
1. A base view object - EmployeesView
2. A child view object extended from EmployeesView - EmpDeptView. Child view object inherits 'EmployeesViewCriteria' defined on base view object.
The EmpDeptViewImpl overrides certain properties of 'EmployeesViewCriteria' from the base view object by using getCriteriaItemAttributeHints(...) method. Take a look at the below shown scree shot to understand this example better. The screen shot displays two query components one from EmployeesView and the other from EmpDeptView. Though both query components are derived from same ViewCriteria defined on the base view object (EmployeesView), the second component displays slightly modified version by hiding the DepartmentId field and marking the FirstName as 'optional'. This is achieved by the altering ViewCriteriaItem instance in the getCriteriaItemAttributeHints(...) method.
Learn More ...
There are a lot more points like this. If you are curious to learn the internals of the ADF Business Components and ADF Binding Layer, the following book is for you - Oracle ADF Real World Developer’s Guide.
More details about this book can be found in this post- http://jobinesh.blogspot.in/2012/07/pre-order-your-copy-of-oracle-adf-real.html
Its time for me to revisit the same topic with slightly different use case :)
The use case requirement was to override the ViewCrtieria hints of a base view object from a child view object. Well, its easy. You can hook your code by overriding ViewObjectImpl::getCriteriaItemAttributeHints(ViewCriteriaItem vci), and optionally return your own AttributeHints implementation. In the following code sample, I'm demonstrating this by changing some properties of a ViewCriteriaItem for specific items.
/**
* By default return null. Subclasses may override to return
* custom AttributeHints implementation for the given criteria item.
*/
@Override
public AttributeHints getCriteriaItemAttributeHints(ViewCriteriaItem vci) {
if (vci != null && vci.getViewCriteria().getName().equals("EmployeesViewCriteria")) {
if (vci.getAttributeDef().getName().equals("FirstName")) {
vci.setRequired(ViewCriteriaItem.VCITEM_OPTIONAL);
} else if (vci.getAttributeDef().getName().equals("DepartmentId")) {
vci.setProperty(ViewCriteriaItem.RENDERED_MODE, ViewCriteriaItem.CRITERIA_RENDERED_MODE_NEVER);
}
}
return super.getCriteriaItemAttributeHints(vci);
}
Before winding up today's post, let me teach you one more useful tip on the same context. An interesting enhancement available with 11.1.2.0.0 release is the ability specify 'Display Width' for each view criteria item while defining a view criteria. This property decides the width of the UI control (displayed inside the query component) at run time. Please note that in previous releases the af:query component was using display width from the view object's attribute definition (by default) to render controls.
Download
You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11.1.2.0.0 (11g R2) + HR Schema]
A glance at the implementation
This sample uses 2 view object
1. A base view object - EmployeesView
2. A child view object extended from EmployeesView - EmpDeptView. Child view object inherits 'EmployeesViewCriteria' defined on base view object.
The EmpDeptViewImpl overrides certain properties of 'EmployeesViewCriteria' from the base view object by using getCriteriaItemAttributeHints(...) method. Take a look at the below shown scree shot to understand this example better. The screen shot displays two query components one from EmployeesView and the other from EmpDeptView. Though both query components are derived from same ViewCriteria defined on the base view object (EmployeesView), the second component displays slightly modified version by hiding the DepartmentId field and marking the FirstName as 'optional'. This is achieved by the altering ViewCriteriaItem instance in the getCriteriaItemAttributeHints(...) method.
Learn More ...
There are a lot more points like this. If you are curious to learn the internals of the ADF Business Components and ADF Binding Layer, the following book is for you - Oracle ADF Real World Developer’s Guide.
More details about this book can be found in this post- http://jobinesh.blogspot.in/2012/07/pre-order-your-copy-of-oracle-adf-real.html
Subscribe to:
Posts (Atom)