Thursday Sep 20, 2012

Displaying Exceptions Thrown or Caught in Managed Beans

Just came a cross a sample written by Steve Muench, which somewhere deep in its implementation details uses the following code to route exceptions to the ADF binding layer to be handled by the ADF model error handler (which can be customized by overriding the DCErrorHandlerImpl class and configuring the custom class in DataBindings.cpx file)

To route an exception to the ADFm error handler, Steve used the following code

((DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry()).reportException(ex); 

The same code however can be used in managed beans as well to enforce consistent error handling in ADF. As an example, lets assume a managed bean method hits an exception. To simulate this, let's use the following code:

public void onToolBarButtonAction(ActionEvent actionEvent) {
   throw new JboException("Just to tease you !!!!!");        
}

The exception shows at runtime as displayed in the following image:

Exception in Managed Bean

Assuming a try-catch block is used to intercept the exception caused by a managed bean action, you can route the error message display to the ADF model error handler. Again, let's simulate the code that would need to go into a try-catch block

public void onToolBarButtonAction(ActionEvent actionEvent) {
   JboException ex = new JboException("Just to tease you !!!!!"); 
   BindingContext bctx = BindingContext.getCurrent();
   ((DCBindingContainer)bctx.getCurrentBindingsEntry()).reportException(ex);
}

The error now displays as shown in the image below

Exception displayed by ADFm error handler

As you can see, the error is now handled by the ADFm Error handler, which - as mentioned before - could be a custom error handler. Using the ADF model error handling for displaying exceptions thrown in managed beans require the current ADF Faces page to have an associated PageDef file (which is the case if the page or view contains ADF bound components).

Note that to invoke methods exposed on the business service it is recommended to always work through the binding layer (method binding) so that in case of an error the ADF model error handler is automatically used.



Wednesday Sep 19, 2012

Oracle ADF Coverage at OOW

Below is the schedule for all ADF related sessions at a glance. Note the Meet and greet session added for Wednesday Octiber 3rd from 4.30 pm to 5:30.

Oracle ADF and Fusion Development

General Session



Time Title Location
10:45 AM - 11:45 AM General Session: The Future of Development for Oracle Fusion—From Desktop to Mobile to Cloud Marriott Marquis - Salon 8
12:15 PM - 1:15 PM General Session: Extend Oracle Fusion Apps to Tablets/Smartphones with Oracle Mobile Technology Moscone West - 3014
1:45 PM - 2:45 PM General Session: Extend Oracle Applications to Mobile Devices with Oracle’s Mobile Technologies Moscone West - 3002/3004
4:45 PM - 5:45 PM General Session: Building Mobile Applications with Oracle Cloud Moscone West - 2002/2004

Conference Session



Time Title Location
12:15 PM - 1:15 PM Understanding Oracle ADF and Its Role in Oracle Fusion Moscone South - 306
1:45 PM - 2:45 PM Building Performant Oracle ADF Business Components to Meet Tomorrow’s Needs Marriott Marquis - Golden Gate C3
3:15 PM - 4:15 PM End-to-End Oracle ADF Development in Eclipse Marriott Marquis - Golden Gate C3
4:45 PM - 5:45 PM Classic Mistakes with Oracle Application Development Framework Marriott Marquis - Salon 7


Time Title Location
10:15 AM - 11:15 AM One Size Doesn’t Fit All: Oracle ADF Architecture Fundamentals Marriott Marquis - Golden Gate C2
10:15 AM - 11:15 AM Oracle Business Process Management/Oracle ADF Integration Best Practices Marriott Marquis - Golden Gate C3
11:45 AM - 12:45 PM Mobile-Enable Oracle Fusion Middleware and Enterprise Applications with Oracle ADF Moscone South - 306
11:45 AM - 12:45 PM Secrets of Successful Projects with Oracle Application Development Framework Marriott Marquis - Golden Gate C2
1:15 PM - 2:15 PM Develop On-Device iPhone and iPad Apps Without Writing Any Objective-C Code Marriott Marquis - Golden Gate C2
1:15 PM - 2:15 PM BPM, SOA, and Oracle ADF Combined: Patterns Learned from Oracle Fusion Applications Moscone West - 3003
1:15 PM - 2:15 PM The Future of Forms Is … Oracle Forms (and Friends) Moscone South - 306
5:00 PM - 6:00 PM Best Practices for Integrating SOAP and REST Service into Oracle ADF Marriott Marquis - Golden Gate C2


Time Title Location
10:15 AM - 11:15 AM Mobile Apps for Oracle E-Business Suite with Oracle ADF Mobile and Oracle SOA Suite Moscone West - 3001
10:15 AM - 11:15 AM Visualize This! Best Practices for Data Visualization in Desktop and Mobile Apps Marriott Marquis - Golden Gate C3
10:15 AM - 11:15 AM Set Up Your Oracle ADF Project and Development Team for Productivity: Seven Essential Tips Marriott Marquis - Golden Gate C2
11:45 AM - 12:45 PM How to Migrate an Oracle Forms Application to Oracle ADF Marriott Marquis - Golden Gate C2
1:15 PM - 2:15 PM Oracle ADF: Lessons Learned in Real-World Implementations Moscone South - 309
3:30 PM - 4:30 PM Oracle ADF Implementations Around the Globe: Best Practices Marriott Marquis - Golden Gate C2
3:30 PM - 4:30 PM Oracle Developer Cloud Services Marriott Marquis - Salon 7
4:30 PM - 5:30 PM Oracle JDeveloper and Oracle ADF: What’s New Hilton San Francisco - Continental Ballroom 5
5:00 PM - 6:00 PM Mobile Solutions for Oracle E-Business Suite Applications: Technical Insight Moscone West - 2020
5:00 PM - 6:00 PM Extending Social into Enterprise Applications and Business Processes Marriott Marquis - Golden Gate C3
5:00 PM - 6:00 PM The Tie That Binds: An Introduction to Oracle ADF Bindings Marriott Marquis - Golden Gate C2


Time Title Location
11:15 AM - 12:15 PM Using Oracle ADF with Oracle E-Business Suite: The Full Integration View Moscone West - 3003
11:15 AM - 12:15 PM Deep Dive into Oracle ADF: Advanced Techniques Marriott Marquis - Golden Gate C2
12:45 PM - 1:45 PM Monitor, Analyze, and Troubleshoot Your Oracle ADF Application Marriott Marquis - Golden Gate C2
2:15 PM - 3:15 PM Oracle WebCenter Portal: Creating and Using Content Presenter Templates Marriott Marquis - Golden Gate C2

HOL (Hands-on Lab)



Time Title Location
10:45 AM - 11:45 AM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A
1:45 PM - 2:45 PM Build Mobile Applications for Oracle E-Business Suite Marriott Marquis - Salon 10A
3:15 PM - 4:15 PM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A
3:15 PM - 4:15 PM Introduction to Oracle ADF: Hands-on Lab Marriott Marquis - Salon 3/4
4:45 PM - 5:45 PM Application Lifecycle Management with Oracle JDeveloper: Hands-on Lab Marriott Marquis - Salon 3/4


Time Title Location
10:15 AM - 11:15 AM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A
5:00 PM - 6:00 PM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A


Time Title Location
10:15 AM - 11:15 AM Introduction to Oracle ADF: Hands-on Lab Marriott Marquis - Salon 3/4
11:45 AM - 12:45 PM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A
1:15 PM - 2:15 PM Build Mobile Applications for Oracle E-Business Suite Marriott Marquis - Salon 10A
3:30 PM - 4:30 PM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A
5:00 PM - 6:00 PM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A


Time Title Location
11:15 AM - 12:15 PM Developing Applications for Mobile iOS and Android Devices with Oracle ADF Mobile: Hands-on Lab Marriott Marquis - Salon 10A
11:15 AM - 12:15 PM Introduction to Oracle ADF: Hands-on Lab Marriott Marquis - Salon 3/4
12:45 PM - 1:45 PM Oracle ADF for Java EE Developers with Oracle Enterprise Pack for Eclipse Marriott Marquis - Salon 3/4

BOF (Birds-of-a-Feather)



Time Title Location
6:15 PM - 7:00 PM How to Get Started with Oracle ADF Marriott Marquis - Club Room
7:15 PM - 8:00 PM Building Next-Generation Applications with Oracle ADF and Oracle BPM Marriott Marquis - Golden Gate C3
7:15 PM - 8:00 PM The Future of Oracle Forms: Upgrade, Modernize, or Migrate? Marriott Marquis - Golden Gate C2
7:15 PM - 8:00 PM Oracle ADF Faces: One Site for Many Devices Marriott Marquis - Golden Gate C1 -

User Group Forum (Sunday Only)



Time Title Location
9:00 AM - 10:00 AM Oracle ADF Immersion: How an Oracle Forms Developer Immersed Himself in the Oracle ADF World Moscone South - 305
10:15 AM - 11:15 AM Deploy with Joy: Using Hudson to Build and Deploy Your Oracle ADF Applications Moscone South - 305
11:30 AM - 12:30 PM ADF EMG User Group: A Peek into the Oracle ADF Architecture of Oracle Fusion Applications Moscone South - 305
12:45 PM - 3:45 PM ADF EMG User Group: Oracle Fusion Middleware Live Application Development Demo Moscone South - 305
3:15 PM - 4:15 PM Mobile Development with Oracle JDeveloper and Oracle ADF Moscone West - 2010

Demos

Demo Location
Developer Moscone North, Upper Lobby - N-002
Oracle ADF Mobile Development Moscone North, Upper Lobby - N-001
Oracle Eclipse Projects Hilton San Francisco, Grand Ballroom - HHJ-008
Oracle Enterprise Pack for Eclipse Moscone South, Right - S-208
Oracle JDeveloper and Oracle ADF Moscone South, Right - S-207
Exhibits
0
Exhibitor Location
Accenture Moscone South - 1813
Moscone South - 2221
Infosys Moscone South - 1701
Moscone South - SMR-005
Innowave Technology Moscone South - 2309
ODTUG Moscone West, Level 2 Lobby - Kiosk in the User Groups Pavilion

Oracle ADF Developers Meet Up

Time Activity Location
4:30 PM - 5:30 PM Stop by the OTN Lounge and meet other Oracle ADF & Fusion developers as well as product managers and engineers who work on Oracle ADF, ADF Mobile and ADF Essentials. Feedback and questions welcome, or simply stop by and say ‘hi!’ and enjoy free beer. OTN Lounge

Wednesday Sep 12, 2012

Iterating selected rows in an ADF Faces table

In OTN Harvest May 2012; http://www.oracle.com/technetwork/developer-tools/adf/learnmore/may2012-otn-harvest-1652358.pdf I wrote about "Common mistake when iterating <af:table> rows". In this entry I showed code to access the row associated with a selected table row from the binding layer to avoid the problem of having to programmatically change the selected table row.

As it turns out, my solution only worked fro selected table rows that are in the current iterator query range. So here's a solution that works for all ranges

public String onButtonPress() {
  RowKeySet rks = table.getSelectedRowKeys();
  Iterator it = rks.iterator();
  while (it.hasNext()) {
   List selectedRowKeyPath = (List)it.next();            
   //table is the JSF component reference created using the table's binding
   //property         
   Row row = ((JUCtrlHierNodeBinding)table.getRowData(selectedRowKeyPath)).getRow();
   System.out.println("Print Test: " + row.getAttribute(1));
  }
   return null;
}


Monday Aug 27, 2012

ADF Partner Community News Session - Open Invitation: "ADF as a basis of Fusion Apps - the biggest ADF project ever (in English)"

After a successful guest performance of Ted Farrell in 2011, this year's international ADF speaker to speak during an ADF News session is Chris Muir from Oracle. 

ADF News Session - Friday September 14, 8:30 AM - 9.00 AM (CET) - Topic: ADF as a basis of Fusion Apps - the biggest ADF project ever (in English)

+++ this webcast will be conducted in English +++

dial-in numbers conc. ADF News Session, Sep. 14 2012


You are invited to join the next ADF News Session, that is going to take place September 14 2012

speaker:  Chris Muir / Oracle
time:         8:30 AM (CET)
duration:  30 minutes
topic:        ADF as a basis of Fusion Apps - the biggest ADF project ever (in English)

dial-in webconf:
https://oraclemeetings.webex.com
conf ID:      595 484 157
confkey:    123456

Please enter your name and an abbreviation of you company name when dialing in (please don´t use blanks and special characters). Please notice that this information will be visible to all participants of the webcast. Thank you.
dial-in telco:

          +49 (0)69 2222 16 106 or +49 (0)800 66 485 15
          ConfCode: 208 503 9
          SecurityPasscode: 112233

 Other toll-free dial in numbers for EMEA countries are listed below (information is supplied without liability):

Austria

0800005967

Belgium

080048331

Croatia

0800222323

Czech Republic

800701080

Denmark 

80889099

Estonia

8000111325

Egypt

08000000213

Finland

0800112073

France

0805632866

Greece

00800127897

Hungary

0680011201

Iceland

8008779

Ireland

1800932479

Israel

1809452571

Italy

800897629

Latvia

80002397

Luxembourg

80026598

Netherlands

08000235028

Norway

80010796

Poland

8001213557

Portugal

800814990

Romania

0800895563

Russia

81080029351012

Saudi Arabia

8008444320

Slovak Republic

0800001586

Slovenia

080080466

South Africa

0800980961

Spain

800098600

Sweden

856619465

Switzerland

0800650026

Turkey

00800 44632129

Ukraine

0800500166

United Arab Emirates

8000440344

United Kingdom

08006948154

 


Tuesday Jul 17, 2012

How-to add new ADF bound table row at the end of a table

A frequent question on OTN, which I often see answered with new rows created on the ADF BC view object level instead the ADF binding layer, is about how to create a new row for a table and append it as the last row in the table. The following code below shows how to do this properly using the binding layer only. Note that while it adds the row as the last row of the table, it doesn't do this as the last row of all possible rows that haven't yet been queried from the database. There is a difference between the last row in a table and the last row in the database.

public String onRowCreate() {
 BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
 //access the name of the iterator the table is bound to. Its "allDepartmentsIterator"
 //in this sample
 DCIteratorBinding dciter = (DCIteratorBinding) bindings.get("allDepartmentsIterator");
 //access the underlying RowSetIterator
 RowSetIterator rsi = dciter.getRowSetIterator();
 //get handle to the last row
 Row lastRow = rsi.last();
 //obtain the index of the last row
 int lastRowIndex = rsi.getRangeIndexOf(lastRow);
 //create a new row
 Row newRow = rsi.createRow();
 //initialize the row
 newRow.setNewRowState(Row.STATUS_INITIALIZED);
 //add row to last index + 1 so it becomes last in the range set
 rsi.insertRowAtRangeIndex(lastRowIndex +1, newRow); 
 //make row the current row so it is displayed correctly
 rsi.setCurrentRow(newRow);                          
 return null;
}  

For the table to show the newly created row after this ensure:

1. The table is configured to always show the current selected row by setting  its displayRow property to selected

2. The table is PPR'ed after the row is created, which can be done declarative using the PartialTriggers property of the table pointing to the ID of the command creating the new row

But what is wrong with the approach of doing the same on the View Object level in ADF BC if it works? Well, it works but it doesn't ensure separation of the layers unless the functionality is exposed as a method on the view object interface. The code in this blog entry is generic and works the same for other business services, like EJB, POJO and Web Services for creating new table rows (which then however you need to persist explicitly in opposite to what you have to do when using ADF BC). So while the other code works, the one in this is the proper solution.

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

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 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.

Tuesday May 29, 2012

Common mistake when iterating rows

In a blog entry from 2010, Oracle's Jobinesh Purushothaman writes about exceptions that are getting raised after developers iterate the collection of a RichTable instance using calls to setRowKey(key).

http://jobinesh.blogspot.co.uk/2010/02/common-mistake-while-iterating-through.html

The reason for the exception is that the selected row state is change on the table without synchronization to happen with the ADF binding layer. The failure of synchronizing the table selected row state with the ADF binding layer is because no row selection event is raised on the table if the row currency is changed programmatically. In theory, if you call #{bindings.treebinding.treeModel.makeCurrent}using a method expression in EL

The failed binding synchronization is because no row selection event is fired when the selected row state is changed on the table using Java in a managed bean.

A solution to this problem could be to call #{bindings.treebinding.treeModel.makeCurrent}from a method expression in Java each time you called setRowKey(key). But, assuming the iteration of rows in a table is for aggregating numeric values or to compare two rows, do you really want to change the current row in the ADF binding layer for each row you need to access?

A better implementation for this use case in my opinion is to read the data from the ADF binding layer instead of the RichTable table instance, which then will not change the row currency at all.

RichTable table = ... get table reference ...
Iterator iter = selectedRowKeys.iterator();
CollectionModel model = (CollectionModel ) table.getValue();
JUCtrlHierBinding treeBinding = (JUCtrlHierBinding )model.getWrappedData();
if (iter != null && iter.hasNext()) {
  Object rowKey = iter.next();
  JUCtrlHierNodeBinding rowData = treeBinding.findNodeByKeyPath(rowKey);     
  //Do something here

}

Note that the reported problem in Jobinesh's blog is for ADF bound tables configured for single row selection. Still I would prefer my approach over changing the selected row state on a table.


Monday Apr 23, 2012

How-to invoke a method once upon application start

A requirement on the OTN forum was to execute a method only once upon application start either for the application as a whole (all user instances) or once per application user session. In addition, the method to be executed was exposed as an Operation binding on the ADF binding layer.

One way to provide a solution to this requirement is to within the combination of a phase listener on the JSPX of JSF document level and a managed bean in application or session scope (dependent on whether the method should be executed once per application start or once per application user session).

The phase listener can be configured on a JSF document, as mentioned or in the faces-config.xml file if there is no single entry to an application. For this example, we assume a single point of entry so that the phase listener can be configured on the f:view attribute.

<f:view beforePhase="#{ManagedBean.onBeforePhase}">

The event logic is configured in a bean in request scope so it could also hold component references for the page if required.

public void onBeforePhase(PhaseEvent phaseEvent) {
 //render response is called on an initial page request 
  if(phaseEvent.getPhaseId() == PhaseId.RENDER_RESPONSE){ 
    FacesContext fctx = FacesContext.getCurrentInstance(); 
    ELContext elctx = fctx.getELContext(); 
    ExpressionFactory exprFactory =
             fctx.getApplication().getExpressionFactory(); 
    //call the managed bean in application or session scope. If the 
    //bean instance already exists, then no new instance of it will be  
    //created,in which case the "initial load" method is not executed 
   
    ValueExpression ve = exprFactory.createValueExpression(
         elctx, 
         "#{your_managed_bean_in_application_or-session_scope", 
         Object.class); 
    ve.getValue(elctx); 
  }
}

The idea for this phase listener is to reference a managed bean in application scope or session scope base on your requirement. The managed bean in session or application scope invokes the method you want to invoke once per application or user session in its post construct method

//Managed Bean in application scope
import javax.annotation.PostConstruct;
... 
@PostConstruct 
public void methodInvokeOncedOnPageLoad(){  
  //access the methods you want to invoke. If they are exposed in the  
  //PageDef file, access the BindingContext --> BindingContainer --> 
  //OperationBinding. Alternatively you can call BindingContext --> 
  //findDataControl("Name as in DataBindings.cpx") --> 
  //getApplicationModule -->  findViewObject/Execute methods 
  ...
}

Note that the Java EE @PostConstruct bean is called once for each bean instantiation. In the managed bean case, the bean is instantiated once per application or session and so is the method executed once.


        
    

Friday Apr 20, 2012

Which option to choose for accessing Web Services in ADF

Oracle ADF provides three options for integrating Web Service:

· Web Service Data Control

· JAX-WS proxy client and POJO Data Control

· JAX-WS proxy client and programmatic View Objects

Note: In the above, I exclude REST services in my recommendation because this is what ADF will address much better using the URL data control in JDeveloper 11g R2 (available) and with improved functionality in the upcoming Oracle JDeveloper 12c release.

For deciding which option to use for integrating Web Service, here is what I consider "a good rule of thumb"

1. Use Web Service Data Control only for simple service like weather reports or stock quotes

2. Use JAX-WS proxy client for all more complex services and access them from

a. Programmatic view object and entity if your business service is ADF Business Components as this allows for better integration with database queried  views

i. Use View Objects only for read only access

ii. Use View Objects and Entities for CRUD Web Service integration

b. POJO Data Control

i. If your business service is not ADF BC.

ii. If the WS doesn't require integration in ADF business component

iii. If WS access should be from a bounded task flow in an ADF library for maximum reuse

As a general hint of best practice: Never use the JAX-WS generated proxy client directly. Always access it from a wrapper bean to avoid code losses or problem in cases where the proxy client needs to be re-generated.

Note: ADF Code Corner published an article explaining how to cache Web Services results when using JAX-WS proxy clients to avoid unnecessary round trips. See: http://www.oracle.com/technetwork/developer-tools/adf/learnmore/92-cache-ws-queries-523136.pdf


        
    

Monday Mar 19, 2012

URL Task Flow vs. WSRP Portlets

A URL task flow is bounded task flow that is deployed as a stand-alone Java EE application on a remote server with its URL Invoke property set to url-invoke-allowed. The URL task flow is accessed either from a direct browser GET request or, when called from another ADF application, through the task flow call activity.

For more information about how to invoke URL task flows from a task flow call activity see chapter 15.6.4 How to Call a Bounded Task Flow Using a URL of the Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework at

http://docs.oracle.com/cd/E23943_01/web.1111/b31974/taskflows_activities.htm#CHDJDJEF

Compared to WRSP portlets, URL task flows in Oracle JDeveloper 11g R1 and R2 have a functional limitation in that they cannot be embedded as a region on a page but require the calling ADF application to navigate off to another application and page. The difference between a URL task flow call using the task flow call activity and a simple redirect to a remote Java EE application is that the URL task flow has a state token attached that allows to restore the state of the calling application upon task flow return.

A use case for a URL task flow call activity is a "yellow page lookup" scenario in which different ADF applications use an URL task flow to lookup people, products or similar to return a selected value to the calling application.

Note that URL task flow calls need to be performed from a bounded or unbounded top level task flow of the calling application. If called from a region (using the parent call activity) in a page, the region state is not recovered upon task flow return.

ADF developers recently have identified URL task flows as an architecture pattern to partition their ADF applications into independently deployed Java EE applications. While this sounds like a desirable use of the URL task flow feature, it is not possible to achieve for as long as URL task flows don't render as an ADF region.

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
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today