Saturday, May 19, 2012

Exception Handling in adf (Part 1)


Exception Handling in ADF

Since Exception handling is very vital part of any web based application and technique of exception handling implementation  is depend on from where it is throwing.
The exception will occurred on following part of the application

1-Model
2-View Controller

It may be Model layer or may be View layer

Moreover the Exception handling approach is base on the layer from where it's thrown .If it is throwing through Model layer then the way of handling is difference compare to if it thrown on the View Controller .

As you all know we are accessing model layer through the binding container. Internally If any exception has thrown by model layer ,then by default the DCErrorHandlerImpl class going to catch the exception and show the  error message to user.(this is default features of ADF).

In some case we do not want to show the exception because as end user they want more specify message.So in this case we need to override default exception .

So first i would like to explain exception handling approach in model layer


Following step will explain the way of exception in model.

1-Create the class and extends with DCErrorHandlerImpl
2-Override the public void reportException(DCBindingContainer bc, Exception ex) .

According your requirement report the exception on DCErrorHandlerImpl.

package com.prateek.blog.view.exception;

import oracle.adf.model.binding.DCBindingContainer;
import oracle.adf.model.binding.DCErrorHandlerImpl;

import oracle.jbo.JboException;

public class CustomExceptionHandler extends DCErrorHandlerImpl {
    public CustomExceptionHandler() {
        super(true);
    }

    @Override
    public void reportException(DCBindingContainer dCBindingContainer,
                                Exception exception) {

        if (exception instanceof JboException) {
            //By default all exception which are coming from Model layer all are instance of JboException
            //here just i am try to skip the exception to report to super class which is DCErrorHandlerInpl
            //we can write our own logic
            // if the exception came of model then it always go through this if condition
        } else {
            super.reportException(dCBindingContainer, exception);
        }

    }

    private void disableAppendCodes(Exception ex) {
        if (ex instanceof JboException) {
            JboException jboEx = (JboException)ex;
            jboEx.setAppendCodes(false);
            Object[] detailExceptions = jboEx.getDetails();
            if ((detailExceptions != null) && (detailExceptions.length > 0)) {
                for (int z = 0, numEx = detailExceptions.length; z < numEx;
                     z++) {
                    disableAppendCodes((Exception)detailExceptions[z]);
                }
            }
        }
    }

    @Override
    public DCErrorMessage getDetailedDisplayMessage(BindingContext bindingContext,
                                                    RegionBinding regionBinding,
                                                    Exception exception) {
        return super.getDetailedDisplayMessage(bindingContext, regionBinding,
                                               exception);
    }

    @Override
    public String getDisplayMessage(BindingContext bindingContext,
                                    Exception exception) {
        return super.getDisplayMessage(bindingContext, exception);
    }

    @Override
    protected boolean skipException(Exception exception) {
        return super.skipException(exception);
    }

}

*This is just a example to just skip the exception.Please see the following link for more information.

1-http://docs.oracle.com/cd/B31017_01/web.1013/b25947/web_val008.htm

3-After Creating our own custom exception handler we need to write this class in DataBinding.cpx as ErrorHandlerClass

<application clienttype="Generic" errorhandlerclass="com.prateek.blog.view.exception.CustomExceptionHandler" id="DataBindings" package="com.prateek.blog.view" separatexmlfiles="false" version="11.1.1.59.23" xmlns="http://xmlns.oracle.com/adfm/application">
  <pagemap>
    <page path="/exceptionPage.jspx" usageid="com_prateek_blog_view_exceptionPagePageDef">
  </page></pagemap>
  <pagedefinitionusages>
    <page id="com_prateek_blog_view_exceptionPagePageDef" path="com.prateek.blog.view.pageDefs.exceptionPagePageDef">
  </page></pagedefinitionusages>
  <datacontrolusages>
    <bc4jdatacontrol configuration="AppModuleLocal" factoryclass="oracle.adf.model.bc4j.DataControlFactoryImpl" id="AppModuleDataControl" package="com.prateek.blog.model" supportsfindmode="true" supportsrangesize="true" supportsresetstate="true" supportssortcollection="true" supportstransactions="true" syncmode="Immediate" xmlns="http://xmlns.oracle.com/adfm/datacontrol">
  </bc4jdatacontrol></datacontrolusages>
</application>

4-The following code which i have written in to backing bean  to show our custom message on UI.

    public void jboException(ActionEvent actionEvent) {
        BindingContainer bindings =
            BindingContext.getCurrent().getCurrentBindingsEntry();
        OperationBinding opeartionBinding =
            bindings.getOperationBinding("throwNewException");
        opeartionBinding.execute();
        if (opeartionBinding.getErrors().size() > 0) {
            FacesContext context = FacesContext.getCurrentInstance();
            FacesMessage message = new FacesMessage("Error message here");
            message.setSeverity(FacesMessage.SEVERITY_ERROR);
            context.addMessage(null, message);
        }

    }

    public void numberPointerException(ActionEvent actionEvent) {
        BindingContainer bindings =
            BindingContext.getCurrent().getCurrentBindingsEntry();
        OperationBinding opeartionBinding =
            bindings.getOperationBinding("throwNewException1");
        opeartionBinding.execute();
        if (opeartionBinding.getErrors().size() > 0) {
            FacesContext context = FacesContext.getCurrentInstance();
            FacesMessage message = new FacesMessage("Error message here");
            message.setSeverity(FacesMessage.SEVERITY_ERROR);
            context.addMessage(null, message);
        }
    }


And upcoming blog i will explain exception handling on task flow and exception handling as global.

This exception handling approach is not going to catch any exception which is thrown from UI

Thanks
Prateek Shaw



2 comments:

  1. Nice explanation dude!
    Keep it Up..

    ReplyDelete
  2. When we work on multi project env, where all (I mean which projects) above classes are to be created? Is it to be a Model project (where we create View and entity objects including app modules) or in UI project (where we create jsff/jspx/backing beans).

    For eg:
    "CustomlExceptionHandler extends DCErrorHandlerImpl", "FacesPageLifecycleBean extends FacesPageLifecycle", and "ADFPhaseListenerBean extends ADFPhaseListener" - where (projects) will these go?

    ReplyDelete