Sunday Jun 24, 2012

How-to dynamically filter model-driven LOV

Often developers need to filter a LOV query with information obtained from an ADF Faces form or other where. The sample below shows how to define a launch popup listener configured on the launchPopupListener property of the af:inputListOfValues component to filter a list of values.

<af:inputListOfValues id="departmentIdId"
   value="#{bindings.DepartmentId.inputValue}"                                      
   model="#{bindings.DepartmentId.listOfValuesModel}"
   launchPopupListener="#{PopupLauncher.onPopupLaunch}" … >      
   …
</af:inputListOfValues>

A list of values is queried using a search binding that gets created in the PageDef file of a view when a lis of value component gets added. The managed bean code below looks this search binding up to then add a view criteria that filters the query.

public void onPopupLaunch(LaunchPopupEvent launchPopupEvent) {
  BindingContext bctx = BindingContext.getCurrent();
  BindingContainer bindings = bctx.getCurrentBindingsEntry();
  JUCtrlListBinding lov = 
       (JUCtrlListBinding)bindings.get("DepartmentId");
  ViewCriteriaManager vcm = 
       lov.getListIterBinding().getViewObject().getViewCriteriaManager();          
  //make sure the view criteria is cleared
  vcm.removeViewCriteria(vcm.DFLT_VIEW_CRITERIA_NAME);
  //create a new view criteria
  ViewCriteria vc = 
         new ViewCriteria(lov.getListIterBinding().getViewObject());
  //use the default view criteria name
  //"__DefaultViewCriteria__"
  vc.setName(vcm.DFLT_VIEW_CRITERIA_NAME);
  //create a view criteria row for all queryable attributes
  ViewCriteriaRow vcr = new ViewCriteriaRow(vc);
  //for this sample I set the query filter to DepartmentId 60. 
  //You may determine it at runtime by reading it from a managed bean
  //or binding layer 
  vcr.setAttribute("DepartmentId", 60);
  //also note that the view criteria row consists of all attributes 
  //that belong to the LOV list view object, which means that you can
  //filter on multiple attributes
  vc.addRow(vcr);           
  lov.getListIterBinding().getViewObject().applyViewCriteria(vc);
} 

Note: Instead of using the vcm.DFLT_VIEW_CRITERIA_NAME name you can also define a custom name for the view criteria.

Friday Jun 22, 2012

Oracle Fusion Applications Design Patterns Now Available

"The Oracle Fusion Applications user experience design patterns are published! These new, reusable usability solutions and best-practices, which will join Oracle dashboard patterns and guidelines that are already available online, are used by Oracle to artfully bring to life a new standard in the user experience, or UX, of enterprise applications. Now, the Oracle applications development community can benefit from the science behind the Oracle Fusion Applications user experience, too.

These Oracle Fusion Applications UX Design Patterns, or blueprints, enable Oracle applications developers and system implementers everywhere to leverage professional usability insight when [...]  designing exciting, new, highly usable applications -- in the cloud or on-premise.

 Based on the Oracle Application Development Framework (ADF) components, the Oracle Fusion Applications patterns and guidelines are proven with real users and in the Applications UX usability labs, so you can get right to work coding productivity-enhancing designs that provide an advantage for your entire business.

 What’s the best way to get started? We’ve made that easy, too. The Design Filter Tool (DeFT) selects the best pattern for your user type and task. Simply adapt your selection for your own task flow and content, and you’re on your way to a really great applications user experience.

More Oracle applications design patterns and training are coming your way in the future. To provide feedback on the sets that are currently available, let us know in the comments section or use the contact form provided."

Thursday Jun 21, 2012

Partial Submit vs. Auto Submit

Partial Submit

ADF Faces adds the concept of partial form submit to JavaServer Faces 1.2 and beyond. A partial submit actually is a form submit that does not require a page refresh and only updates components in the view that are referenced from the command component PartialTriggers property. Another option for refreshing a component in response to a partial submit is call AdfContext.getCurrentInstance.addPartialTarget(component_instance_handle_goes_here)in a managed bean. If a form contains required fields that the user left empty invoking the partial submit, then errors are shown for each of the field as the full form gets submitted.

Autosubmit

An input component that has its autosubmit property set to true also performs a partial submit of the form. However, this time it doesn't submit the entire form but only the component that triggers the submit plus components referenced it in their PartialTriggers property.

For example, consider a form that has three input fields inpA, inpB and inpC with autosubmit=true set on inpA and required=true set on inpB and inpC.

use case 1: Running the view, entering data into inpA and then tabbing out of the field will submit the content for inpA but not for inpB and inpC. Further more, none of the required field settings on inpB and inpC causes an error.

use case 2: You change the configuration of inpC and set its PartialTriggers property to point to the ID of component inpA. When rerunning the sample, entering a value into inpA and tabbing out of the field will now submit the inpA and inpC fields and thus show an error for the missing required value on inpC.

Internally, using autosubmit=true on an input component sets the event root to just this field, which good to have in case of dependent field validation or behavior. The event root can extended to include other components by using the Partial Triggers property on these components to point to the input field that has autosubmit=true defined.

PartialSubmit vs. AutoSubmit

Partial submit set on a command component submits the whole form and leaves it to the developer to decide which UI component is refreshed in response. Client side required field validation (as well as the server side equivalent) is not disabled by executed in this scenario. Setting immediate=true on the command item to skip validation doesn't help as it would also skip the model update.

Auto submit is a functionality on the input components and also performs a partial form submit. However, in addition an event root is defined that narrows the scope for the submitted data and thus the components that are validated on the request.

To read more about this topic, see: http://docs.oracle.com/cd/E23943_01/web.1111/b31973/af_lifecycle.htm#CIAHCFJF

When JDeveloper IDE doesn't render the visual editor

Though with Oracle JDeveloper 11g the problem of the IDE not rendering JSF pages properly in the visual editor has become rare, there always is a way for the creative to break IDE functionality. A possible reason for the visual editor in JDeveloper to break is a failed dependency reference, which often is in a custom JSF PhaseListener configured in the faces-config.xml file. To avoid this from happening, surround the code in your PhaseListener class with the following statement (for example in the afterPhase method)

public void afterPhase(PhaseEvent phaseEvent) {
  if(!ADFContext.getCurrent().isDesigntime()){
    ... listener code here ...
  }
}

The reason why the visual editor in Oracle JDeveloper fails rendering the WYSIWYG view has to do with how the live preview is created. To produce the visual display of a view, JDeveloper actually runs the ADF Faces view in JSF, which then also invokes defined PhaseListeners. With the code above, you check whether the PhaseListener code is executed at runtime or design time.If it is executed in design time, you ignore all calls to external resources that are not available at design time.

OEPE with ADF binding support available: Total Eclipse

The current release of Oracle Enterprise Pack for Eclipse, though in technology preview, brings Oracle ADF binding to the Eclipse IDE. You can download the Software from the link below:

Oracle Enterprise Pack for Eclipse (12.1.1.1.0) Technical Preview New June 2012
Certified on Windows 7/XP/Vista, MacOS, and Linux. Supported on JDK 6.

For many Eclipse users, ADF is new and therefore I expect them to need guidance and help in case they run into issues they don't know how to recover from. Similar, ADF users familiar with Oracle JDeveloper that want to give OEPE a try, will find things different in Eclipse and thus may have questions. 

For both audiences I suggest to post issues to the OEPE forum on the Oracle Technology Network: I'll extend my OTN monitoring to include the OEPE forum on a daily basis to learn about developer needs, requirements and - of course - to catch bugs that need to be filed. From my side this is a part-time involvement, which means that the more ADF questions show on the forum, the more help I could need in answering them. The OTN forum for JDeveloper in my opnion wouldn't be the right place to go to unless the question is a generic ADF question that is not dependent on the integration in Eclipse.

Here's the OEPE forum link for a start

https://forums.oracle.com/forums/forum.jspa?forumID=578

Frank


Wednesday Jun 20, 2012

Free Advanced ADF eCourse, part II

A second part of the advanced Oracle ADF online training is available for free. Lynn Munsinger and her team worked hard to deliver this second part of the training as close to the release of the first installment as possible. This two part advanced ADF training provides you with a wealth of advanced ADF know-how and insight for you to adopt in a self-paced manner.

Part 1 (though I am sure you have this bookmarked):

http://tinyurl.com/advadf-part1

Part 2 (the new material):
http://tinyurl.com/advadf-part2

Quoting Lynn:

"This second installment provides you with all you need to know about regions, including best practices for implementing contextual events and other region communication patterns.

It also covers the nitty-gritty details of building great looking user interfaces, such as how to work with (not against!) the ADF Faces layout components, how to build page templates and declarative components, and how to skin the application to your organization’s needs. It wraps up with an in-depth look at layout components, and a second helping of additional region considerations if you just can’t get enough.

Like the first installment, the content for this course comes from Product Management. This 2nd eCourse compilation is a bit of a “Swan Song” for Patrice Daux, a long-time JDeveloper and ADF curriculum developer, who is retiring the end of this month. Thanks for your efforts, Patrice, and bon voyage!"

Indeed: Great job Patrice! (and all others involved)

Monday Jun 18, 2012

Pretty URL in ADF Faces of JDeveloper 11.1.2.2

Many features planned for Oracle JDeveloper 12c find their way into current releases of Oracle JDeveloper 11g R1 and JDeveloper 11g R2. One example of such a feature is "pretty URL" - or "clean URL" as the Oracle JDeveloper 11g R2 (11.1.2.2) documentation puts it.

"A.2.3.24 Clean URLs

Historically, ADF Faces has used URL parameters to hold information, such as window IDs and state. However, URL parameters can prevent search engines from recognizing when URLs are actually the same, and therefore interfere with analytics. URL parameters can also interfere with bookmarking.

By default, ADF Faces removes URL parameters using the HTML5 History Management API. If that API is unavailable, then session cookies are used.

You can also manually configure how URL parameters are removed using the context parameter oracle.adf.view.rich.prettyURL.OPTIONS. Set the parameter to off so that no parameters are removed. Set the parameter to useHistoryApi to only use the HTML5 History Management API. If a browser does not support this API, then no parameters will be removed. Set the parameter to useCookies to use session cookies to remove parameters. If the browser does not support cookies, then no parameters will be removed."

See: http://docs.oracle.com/cd/E26098_01/web.1112/e16181/ap_config.htm#ADFUI12856

So basically, what this part in the documentation says is:

  • In JDeveloper 11g R2 (11.1.2.2), Oracle ADF Faces automatically removes its internally used dynamic parameters from the URL
  • You can influence the setting with the prettyURL.OPTIONS context option, which however is not recommended you to do because the default behavior is able to detect if the browser client supports HTML 5 History management or not. In the latter case it the uses a session cookie and if this doesn't work, falls back to the "old" URL parameter adding.
The information that is not so explicit and clearly mentioned in the documentation is that this is only for ADF Faces parameters (such as _afrLoop, Adf-Window-Id, etc.), but not the ADF controller token (_adf.ctrl-state)! Removing the ADF controller token is an enhancement request that will be implemented in Oracle JDeveloper 12c

af:inputSlider doesn't render in popup for FF, Safari and Chrome

A problem reported on OTN is that the af:inputSlider component of Oracle JDeveloper 11.1.2.2 doesn't show on all browsers except IE when the slider is added as the sole component in a popup. The problem reproduces with the ADF Faces component demo and I filed bug 14207690. The work around, posted by OTN user "Tses" is to set the inlineStyle property on the slider to table

<af:inputNumberSlider ... inlineStyle="display:table;"/>

Tuesday Jun 12, 2012

Programmatically disclosing a node in af:tree and af:treeTable

A common developer requirement when working with af:tree or af:treeTable components is to programmatically disclose (expand) a specific node in the tree.

If the node to disclose is not a top level node, like a location in a LocationsView -> DepartmentsView -> EmployeesView hierarchy, you need to also disclose the node's parent node hierarchy for application users to see the fully expanded tree node structure. Working on ADF Code Corner sample #101, I wrote the following code lines that show a generic option for disclosing a tree node starting from a handle to the node to disclose.

The use case in ADF Coder Corner sample #101 is a drag and drop operation from a table component to a tree to relocate employees to a new department. The tree node that receives the drop is a department node contained in a location. In theory the location could be part of a country and so on to indicate the depth the tree may have. Based on this structure, the code below provides a generic solution to parse the current node parent nodes and its child nodes.

The drop event provided a rowKey for the tree node that received the drop. Like in af:table, the tree row key is not of type oracle.jbo.domain.Key but an implementation of java.util.List that contains the row keys. The JUCtrlHierBinding class in the ADF Binding layer that represents the ADF tree binding at runtime provides a method named findNodeByKeyPath that allows you to get a handle to the JUCtrlHierNodeBinding instance that represents a tree node in the binding layer.

CollectionModel model = (CollectionModel) your_af_tree_reference.getValue();
JUCtrlHierBinding treeBinding = (JUCtrlHierBinding ) model.getWrappedData();
JUCtrlHierNodeBinding treeDropNode = treeBinding.findNodeByKeyPath(dropRowKey);

To disclose the tree node, you need to create a RowKeySet, which you do using the RowKeySetImpl class. Because the RowKeySet replaces any existing row key set in the tree, all other nodes are automatically closed.

RowKeySetImpl rksImpl = new RowKeySetImpl();
//the first key to add is the node that received the drop
//operation (departments).            
rksImpl.add(dropRowKey);    

Similar, from the tree binding, the root node can be obtained. The root node is the end of all parent node iteration and therefore important.

JUCtrlHierNodeBinding rootNode = treeBinding.getRootNodeBinding();

The following code obtains a reference to the hierarchy of parent nodes until the root node is found.

JUCtrlHierNodeBinding dropNodeParent = treeDropNode.getParent();
//walk up the tree to expand all parent nodes 
while(dropNodeParent != null && dropNodeParent != rootNode){
   //add the node's keyPath (remember its a List) to the row key set
   rksImpl.add(dropNodeParent.getKeyPath());   
   dropNodeParent = dropNodeParent.getParent();
}

Next, you disclose the drop node immediate child nodes as otherwise all you see is the department node. Its not quite exactly "dinner for one", but the procedure is very similar to the one handling the parent node keys

ArrayList<JUCtrlHierNodeBinding> childList = (ArrayList<JUCtrlHierNodeBinding>) treeDropNode.getChildren();                     
for(JUCtrlHierNodeBinding nb : childList){
  rksImpl.add(nb.getKeyPath());
}

Next, the row key set is defined as the disclosed row keys on the tree so when you refresh (PPR) the tree, the new disclosed state shows

tree.setDisclosedRowKeys(rksImpl); 
AdfFacesContext.getCurrentInstance().addPartialTarget(tree.getParent()); 

The refresh in my use case is on the tree parent component (a layout container), which usually shows the best effect for refreshing the tree component. 

Monday Jun 11, 2012

Solving the context menu problem with drag and drop in trees

The following drag-and-drop problem has been reported on OTN: An ADF Faces tree component is configured with a af:collectionDropTarget tag to handle drop events. The same tree component also has a context menu defined that is shown when users select the tree with the right mouse button. The problem now was - and I could reproduce this - that the context menu stopped working after the first time the tree handled a drop event. The drag and drop use case is to associate employees from a table to a department in the tree using drag and drop.

The drop handler code in the managed bean looked up the tree node that received the drop event to determine the department ID to assign to the employee. For this code similar to the one shown below was used

List dropRowKey = (List) dropEvent.getDropSite();
//if no dropsite then drop area was not a data area
if(dropRowKey == null){
   return DnDAction.NONE;
}                

tree.setRowKey(dropRowKey);
JUCtrlHierNodeBinding dropNode = (JUCtrlHierNodeBinding) tree.getRowData();

So what happens in this code? The drop event contains the dropSite reference, which is the row key of the tree node that received the drop event. The code then sets the key to the tree in a call to getRowDate() returns the node information for the drop target (the department). This however causes the tree state to go out of synch with its model (ADF tree binding), which is known to cause issues.

In this use case the issue caused by this is that the context menu no longer shows up. To fix the problem, the code needs to be changes to read the current row key from the key, then perform the drop operation and at the end set the origin (or model) row key back

//memorize current row key
Object currentRowKey = tree.getRowKey();        
List dropRowKey = (List) dropEvent.getDropSite();
//if no dropsite then drop area was not a data area
  if(dropRowKey == null){
    return DnDAction.NONE;
  }              
tree.setRowKey(dropRowKey);
JUCtrlHierNodeBinding dropNode = (JUCtrlHierNodeBinding) tree.getRowData();
... do your stuff here ....
//set current row key back
tree.setRowKey(currentRowKey);
AdfFacesContext.getCurrentInstance().addPartialTarget(tree);

Note the code line that sets the row key back to its original value.

About

The Oracle JDeveloper forum ranks in the Top 5 of the most active forums on the Oracle Technology Network (OTN).



The OTN Harvest blog is a summary of selected topics posted on the OTN Oracle JDeveloper forum.



It is an effort to turn knowledge exchange into an interesting read for developers who enjoy little nuggets of wisdom





Frank Nimphius

Search

Archives
« June 2012 »
SunMonTueWedThuFriSat
     
1
2
3
4
5
6
7
8
9
10
13
14
15
16
17
19
23
25
26
27
28
29
30
       
Today