Tuesday, August 18, 2015

ADF Error Handling

Exceptions are thrown in different places or layers of the ADF application. ADF framework allow applications to register general error handlers on different layers. 



Task Flow Error Handling

Create a task flow called base-taskflow-template.xml. 

In base-taskflow-template.xml, 
  • create a bean class TashFlowErrorHandler. In the class, create a method called 
public void handleException() {//add handling logic}
  • add it to base-taskflow-template.xml as request scope.
  • add a method-call named ErrorHandler, marked it as Exception Handler.
All task flows extend base-taskflow-template.xml. So exceptions are handled by the registered handler.



Bean Exception Handling

When the ADF view layer calls a method from a managed bean and this method throws an exception, the default ADFExceptionHandler is called. To override the default behavior,  

Create class BeanExceptionHandler
public class BeanExceptionHandler extends ExceptionHandler

To register the exception handler, create a file called "oracle.adf.view.rich.context.ExceptionHandler"
add text (class full qualified name) in the file:

com.abc.view.util.BeanExceptionHandler

put this file in master application (deployed as ear file) under folder below (create if doesn't exist)

.adf\META-INF\services




Binding Error Handler

Managed bean may call Application Module methods by DataControls. Such calls use the bindings which are handled by the DataBindings.cpx mainly. 

Create a class called 
public class BindingErrorHandler extends DCErrorHandlerImpl

In master application DataBindings.cpx, we define the ErrorHandlerClass="com.abc.view.util.BindingErrorHandler




Wednesday, July 29, 2015

UIComponent binding in cluster environment


There are two posts mentioned about how UIComponent buiding works in cluster environment:

http://www.ateam-oracle.com/rules-and-best-practices-for-jsf-component-binding-in-adf/
https://adfblog.wordpress.com/2014/08/14/adf-for-high-availability/

in short,
  • All Manage Beans must implement Serializable.
  • UI component bindings must be declared in a bean with shorter scope (backing bean scope or request scope).
  • If it needs to be declared in Manage Bean with PageFlowScope (Not recommended), please ensure you declare the binding as transient.
  • ......

And interested in the class below:
org.apache.myfaces.trinidad.util.ComponentReference
https://java.net/jira/browse/ADFEMG-202

Wednesday, June 10, 2015

locale set up in ADF pages

For a page to change language and formatting of date, we need to set user locale

<f:view locale="#{sessionScope.UserLocale}"...

Friday, January 30, 2015

ADF Component id and clientId

When we drag a ADF component to a page, ADF will generate an id like below:

<af:inputText id="it1" />

The id attribute rendered in the browser is obviously not the same as the value set in the ADF apge. This new id is the clientId and is produced by the UIComponent.getClientId(FacesContext) method.

public String getClientId(String componentId) {
    FacesContext context = FacesContext.getCurrentInstance();
    UIViewRoot root = context.getViewRoot();    
    UIComponent c = findComponent(root, componentId);
    return c.getClientId(context);
}

One good example of using client id is to display error message on a specific field.

The field will has a red border and mouse over to see the error message.
    
public static void displayMessage(Severity messageType,
                                      String messageTitle, String messageText,
                                      String componentId) {
        String clientId = null;
        if (componentId != null) {
            clientId = getClientId(componentId);
        }
        FacesContext fc = FacesContext.getCurrentInstance();
        FacesMessage message = new FacesMessage(messageTitle, messageText);
        message.setSeverity(messageType);
        fc.addMessage(clientId, message);

}




Wednesday, January 21, 2015

How to write CSS class in ADF


Following is an example of write CSS class. The advantage of using CSS class is to apply style to a specific component and do not affect the same component on other pages.

  1. .yourClassName af|inputFile:update::content span:first-of-type {   
  2.     max-width230px;   
  3.     display: inline-block;   
  4.     overflowhidden;   
  5.     text-overflow: ellipsis;   

Wednesday, January 7, 2015

RowSetIterator next never returns null, causing infinite loop

The recommended way of using "RowSetIterator" for a view object:

Always create a "Secondary Row Set Iterator" and close it when finished.
Do not use getRowSetIterator() as it impacts row currency on the front end so firstly you should use createRowSetIterator and you should call closeRowSetIterator on the iterator created through this because if you don't, framework will create new ViewRowSetIteratorImpl instances and keep on adding them.

Code example:
DCBindingContainer bc = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
EmpVOImpl empVoImpl=(EmpVOImpl)bc.findIteratorBinding("EmpVO1Iterator").getViewObject();
    
RowSetIterator it = empVoImpl.createRowSetIterator(null);
while(it.hasNext()){
    EmpVORowImpl row=(EmpVORowImpl)it.next();
    if(row.getSal()!=null){
        totalAmount=row.getSal().add(totalAmount);
    }
}
it.closeRowSetIterator();
If necessary, use finally block

           try{
               while(it.hasNext()){
            EmpVORowImpl row=(EmpVORowImpl)it.next();
            if(row.getSal()!=null){ 
                  totalAmount=row.getSal().add(totalAmount);
            }
        }
} catch(Exception e) {
              //handle here
} finally {
      it.closeRowSetIterator();
}

Please refer to the links below for the issue:
https://community.oracle.com/thread/2242010
http://ramannanda.blogspot.ca/2013/04/adf-examining-memory-leaks.html
http://adfbugs.blogspot.ca/2009/07/iterating-through-view-object.html

https://community.oracle.com/message/12788828#12788828