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

Friday May 04, 2012

Scope object serialization failed (object not serializable)

A common reason for the "SEVERE: ADFc: Scope object serialization failed (object not serializable)" error message is that application developers reference JSF components in managed beans with a scope larger than request. When using the JSF component Binding property to point to a managed bean, think backing bean and thus don't reference beans that are in scopes larger than request scope (don't: viewScope, pageFlowSope, sessionScope, applicationScope).

If, from a managed bean in a scope larger than request you need to have access to a component instance (though the other way around is a more common use case) then either

As mentioned, a more common use case is to access a bean in a scope larger than request from a backing bean. A use case for this is if you need to remember a specific state, like a list of selected values in a select many list, or the disclosure state of panel tabs.

In this case you would save the state information in a bean with a lifecycle that spans beyond request scope and access it from a request scope backing bean using a managed property or by resolving EL in Java.

Monday Mar 05, 2012

Creating a custom master-detail presentation using af:panelAccordion

ADF Code Corner sample #81 explains how-to create a custom layout to render master-detail information. In the sample ADF Faces panel tabs are used to render the master data and DVT components are used in the panel tabs to show the detail information.

http://www.oracle.com/technetwork/developer-tools/adf/learnmore/81-master-detail-tab-with-graphs-394252.pdf

http://www.oracle.com/technetwork/developer-tools/adf/learnmore/81-master-detail-tab-with-graphs-394253.zip

ADF Code Corner Sample 81

The sample reads master information from the selected panel tab to then – using Java in a managed bean – query the detail record for the DVT component. While the solution documented on ADF Code Corner is efficient, there exists another one that is declarative.

Note: of course there are differences in the usage, but this I'll discuss later

The image below shows an ADF Faces panel accordion that displays the HR schema Departments table information on the accordion tabs and information about contained Employees in a panel box that shows when the accordion is expanded.

MdPresentationWithPanelAccordion

This sample uses an ADF tree binding to render the panel accordion tabs and the contained employee detail information. The iteration is done by two af:forEach tags, as shown below

<af:panelAccordion id="pa1" dimensionsFrom="auto">
 <af:forEach items="#{bindings.allDepartmentsWithEmployees.children}" var="departmentsVar">
   <af:showDetailItem text="#{departmentsVar.DepartmentName}" id="sdi1"
                      stretchChildren="first">
    <af:panelBox text="Employees" id="pb1" showDisclosure="false" type="stretch">
       <f:facet name="toolbar"/>
          <af:panelGroupLayout id="pgl1" layout="scroll">
             <af:forEach items="#{departmentsVar.children}" var="employeesVar">
                 <af:outputText id="ot1"
                                value="#{employeesVar.FirstName} #{employeesVar.LastName}"/>
              </af:forEach>
          </af:panelGroupLayout>
      </af:panelBox>
    </af:showDetailItem>
  </af:forEach>
</af:panelAccordion> 

Note that the departmentVar variable is not accessible within the body of the second af:forEach component. While it can be used to configure the second af:forEach component data access, the variable cannot be referenced from the af:panelBox within the second af:forEach component

As shown in the page source above, the first af:forEach tag reads the parent information from the ADF tree binding. Make sure you set the iterator binding for the tree binding to -1 for the RangeSize property as otherwise you would only see the first 10 parent row. 

(PageDef file)

<executables>
  <variableIterator id="variables"/>
  <iterator Binds="allDepartmentsWithEmployees" RangeSize="-1" DataControl="AppModuleDataControl"
            id="allDepartmentsWithEmployeesIterator" Refresh="deferred"/>
</executables> 

Sample Download

You can download the Oracle JDeveloper 11g R2 (11.1.2.1) sample from here. Just configure the database connection to point to an Oracle database with the HR schema unlocked. The ADF BC model is configured to only show departments that have employees (using a ViewCriteria)

Which solution to choose ?

And Finally, what's the difference between this declarative approach and the  more code centric solution in ADF Code Corner sample 81? The difference is that this sample fetches all data upon rendering of the panel accordion, which may be expensive if we talk about thousands of child (employee) records. The sample on ADF Code Corner queries the detail data when a panel tab is selected. Sample 81 on ADF Code Corner however doesn't cache the data of previously selected panels and thus always re-fetches detail data. When working with large data sets however he solution on ADF Code Corner performs better.

Tuesday Feb 28, 2012

Best practice invoking business services methods from JSF beans

Recently there was an increasing interest on OTN in best practices for invoking methods exposed on the ADF Business Components client interface. There exist two options to access methods exposed on ADF Business Components application modules and view objects from a managed bean through ADF.

  • Call findDataControl(String) on the BindingContext and access the application module to invoke a method exposed on the Application Module or View Object client interface.

  • Create a method binding on a PageDef level that binds to a method exposed on the Application Module or View Object client interface

Speaking of best practices, it’s the second option  to use a method binding on the PageDef file that I recommend for the following reasons

  • ADF is about abstracting the view and controller layer from the business service implementation details. A method binding instead exposes an ID (the name o the binding) to the JSF developer, which they use to access the binding from a managed bean using the OperationBinding API. Signature or name changes of a method exposed on the business service thus don't require a change in the managed bean(s) referencing it. All changes would be applied in metadata.

  • ADF provides the OperationBinding class as an abstraction for business services methods. Configuring business service method access on the PageDef file using method bindings exposes a single and consistent API to application developers.

  • Programmatic access to a method exposed on the business service require more lines of code than accessing the same method through the binding layer

  • Direct business service access violates the recommendation to always work through the ADF binding layer and not to bypass it.

To access a method binding from a managed bean, use the following code

  BindingContext bctx = BindingContext.getCurrent();
  BindingContainer bindings = bctx.getCurrentBindingsEntry();
  OperationBinding operationBinding = 
       bindings.getOperationBinding("name_of_method_binding");
  //optional
  operationBinding.getParamsMap().put("argumentName1",value1);
  operationBinding.getParamsMap().put("argumentName2",value2);
  //invoke method
  operationBinding.execute();
  if (!operationBinding.getErrors().isEmpty()) {
     //check errors
     List errors = operationBinding.getErrors();
     ...
  }
  //optional
  Object methodReturnValue = operationBinding.getResult();


Sunday Jan 15, 2012

How-to invoke ADF bindings in page templates

ADF Faces page templates may have their own PageDef file defined to access the ADF binding layer or have ADF bound components added to the template.

ADF Faces pages that use the template will reference the template's PageDef file in the Executable section of their own PageDef file. In this sample, the template binding reference in the the template consumer page PageDef file is ptb1.

The code below invokes a method binding in the template's PageDef file from a command button on the page. The "trick" for accessing the template's PageDef file is to know that it is another instance of BindingContainer.

public String cb1_action() {
  BindingContext bctx = BindingContext.getCurrent();
  DCBindingContainer bindings = 
                (DCBindingContainer)bctx.getCurrentBindingsEntry();
  //access the page template Pagedef file reference in the 
  //Executable section of the consumer page's Pagedef file
  DCBindingContainer templateBinding = 
                    (DCBindingContainer)bindings.get("ptb1");
  //get the MethodBinding 
  OperationBinding printMethod = 
        (OperationBinding)templateBinding .get("printThis");
  //invoke the print method exposed on the template's PageDef file
  printMethod.getParamsMap().put("message","Hello World");
  printMethod.execute();
  return null;
}
 
  

Wednesday Jan 11, 2012

Display selected table row number and total rows

A question on OTN was how to display the current row number and the number of totally available rows in a formatted output string. In the example used below, the format is
row no. [<row index>] of max rows [<total numbers of rows>]

For this example, I used an af:outputText component to display the information on the page. The value of the af:outputText component is calculated from expression language (EL) accessing the ADF binding layer as shown below. Note that for better readability the EL includes line breaks, which in your application you should not add.

 row no. [

#{(bindings.allDepartmentsIterator.rangeStart < 0 ?
1 : bindings.allDepartmentsIterator.rangeStart+1) +

( bindings.allDepartmentsIterator.currentRowIndexInRange == -1 ?

0 : bindings.allDepartmentsIterator.currentRowIndexInRange)}
]

of max rows[

#{bindings.allDepartmentsIterator.estimatedRowCount}]

Note how the expression uses the iterator binding in the ADF binding layer to determine the maximum number of table rows. It then uses the same iterator to determine the current row. Because iterators are zero based, the EL uses additional logic to compensate this.

The af:outputText component needs to have its PartialTriggers property pointing the the af:table component ID to ensure the displayed information is refreshed when the table row currency changes.

 <af:outputText value="row no. [#{(bindings.allDepartmentsIterator.rangeStart &lt; 0 ? 1  :  bindings.allDepartmentsIterator.rangeStart+1) +( bindings.allDepartmentsIterator.currentRowIndexInRange ==  -1 ? 0 : bindings.allDepartmentsIterator.currentRowIndexInRange)}] of max rows [#{bindings.allDepartmentsIterator.estimatedRowCount}]"
                id="ot1" partialTriggers="pc1:t1"/>


Monday Jun 20, 2011

Getting selected row in inputListOfValues returnPopupListener

Model driven list-of-values in Oracle ADF are configured on the ADF Business component attribute which should be updated with the user value selection. The value lookup can be configured to be displayed as a select list, combo box, input list of values or combo box with list of values.

Displaying the list in an af:inputListOfValues component shows the attribute value in an input text field and with an icon attached to it for the user to launch the list-of-values dialog.

The list-of-values dialog allows users to use a search form to filter the lookup data list and to select an entry, which return value then is added as the value of the af:inputListOfValues component.

Note: The model driven LOV can be configured in ADF Business Components to update multiple attributes with the user selection, though the most common use case is to update the value of a single attribute.

A question on OTN was how to access the row of the selected return value on the ADF Faces front end. For this, you need to know that there is a Model property defined on the af:inputListOfValues that references the ListOfValuesModel implementation in the model. It is the value of this Model property that you need to get access to.

The af:inputListOfValues has a ReturnPopupListener property that you can use to configure a managed bean method to receive notification when the user closes the LOV popup dialog by selecting the Ok button. This listener is not triggered when the cancel button is pressed. The managed bean signature can be created declaratively in Oracle JDeveloper 11g using the Edit option in the context menu next to the ReturnPopupListener field in the PropertyInspector. The empty method signature looks as shown below

public void returnListener(ReturnPopupEvent returnPopupEvent) { }

The ReturnPopupEvent object gives you access the RichInputListOfValues component instance, which represents the af:inputListOfValues component at runtime. From here you access the Model property of the component to then get a handle to the CollectionModel.

The CollectionModel returns an instance of JUCtrlHierBinding in its getWrappedData method. Though there is no tree binding definition for the list of values dialog defined in the PageDef, it exists. Once you have access to this, you can read the row the user selected in the list of values dialog. See the following code:

public void returnListener(ReturnPopupEvent returnPopupEvent) {  
  //access UI component instance from return event
  RichInputListOfValues lovField = 
       (RichInputListOfValues)returnPopupEvent.getSource();
  
  //The LOVModel gives us access to the Collection Model and 
  //ADF tree binding used to populate the lookup table
  ListOfValuesModel lovModel =  lovField.getModel();
  CollectionModel collectionModel =
         lovModel.getTableModel().getCollectionModel();   
  
  //The collection model wraps an instance of the ADF 
  //FacesCtrlHierBinding, which is casted to JUCtrlHierBinding
  JUCtrlHierBinding treeBinding =   
         (JUCtrlHierBinding) collectionModel.getWrappedData();
  
  //the selected rows are defined in a RowKeySet.As the LOV table only
  //supports single selections, there is only one entry in the rks
  RowKeySet rks = (RowKeySet) returnPopupEvent.getReturnValue();
  
  //the ADF Faces table row key is a list. The list contains the 
  //oracle.jbo.Key
  List tableRowKey = (List) rks.iterator().next();
  
  //get the iterator binding for the LOV lookup table binding  
  DCIteratorBinding dciter = treeBinding.getDCIteratorBinding();
  
  //get the selected row by its JBO key  
  Key key = (Key) tableRowKey.get(0);
  Row rw =  dciter.findRowByKeyString(key.toStringFormat(true));

  //work with the row
  // ...

}
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