Tuesday, November 7, 2017

Exception Handling in ADF in all the layer-ADF BC,View Layer,Taskflow level

ADF Exception handling can be done at below three places:

  1. Extending DCErrorHandlerImpl
  2. Extending Controller level ExceptionHandler
  3. Taskflow Exception Handler
Lets Discuss in brief:

    1. Extending DCErrorHandlerImpl- for model
Custom ExceptionHandler Class for model

package xx.view.exp.model;

import javax.faces.application.FacesMessage;
import oracle.adf.model.binding.DCErrorHandlerImpl;
import oracle.adf.model.BindingContext;
import oracle.adf.model.binding.DCBindingContainer;
import oracle.jbo.JboException;

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

  public XxModelExpHandler(boolean b)
  {
    super(b);
  }

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

  @Override
  public void reportException(DCBindingContainer formBnd, Exception ex)
  {
    if (ex instanceof XxCustomException)
    {
//get message to be displayed from resource bundle or hardcode the message when throwing exception
        String msg = XxUtils.getMessageString((XxCustomException) ex);
        JboException jex=new JboException(msg);
        super.reportException(formBnd,jex);
    }

    else
    {
      super.reportException(formBnd, ex);
    }
  }

}

Databindings.cpx

Specify your custom handler as ErrorHandlerClass in databindings.cpx:


<Application xmlns="http://xmlns.oracle.com/adfm/application"
             version="11.1.1.59.23" id="DataBindings" SeparateXMLFiles="false"
             Package="xx.view" ClientType="Generic"
             ErrorHandlerClass="xx.view.exp.model.XxModelExpHandler">




2.  Extending Controller level ExceptionHandler
Any exception in controller will first come here and if re-thrown will be handled at taskflow level(explained before).

Declaring custom exception handler class

You need to create a folder named services under Application Resources -> Descriptors -> ADF META-INF. Under the folder create a file named oracle.adf.view.rich.context.ExceptionHandler and inside the file just mention the name of your custom exception handler.



Custom Exception Class

We are creating a custom exception class which will be thrown in our code whenever we want to show a faces message for any validation, failure, etc.


public class XxCustomException
  extends JboException
{
  private String resourceBundleKey;
  private String error_type;
  private String client_id;
  private MessageToken[] tokens;
  
//setters and getters with required constructors
}

Custom ExceptionHandler Class

import oracle.adf.view.rich.context.ExceptionHandler;
public class XxControllerExpHandler
  extends ExceptionHandler
{
  public void handleException(FacesContext facesContext,
                              Throwable throwable, PhaseId phaseId)
    throws Throwable
  {

boolean isCustomExp  = false;
    for (int i = 0; i < 10; i++)
    {
      if (throwable instanceof XxCustomException)
      {
        isCustomExp = true;
        break;
      }
      if (throwable != null)
      {
        throwable = throwable.getCause();
      }
   }

    if (isCustomExp)
    {
      if (throwable!= null)
      {


// The below method will show a Faces Message. If client id of xxCustomException is not null then it will show a faces message on that component. It will try to get the message from resource bundle based on resourceBundleKey attribute. Error_type will decide if it is info, warning, severe

        XxUtils.showMessage((XxCustomException)throwable);
      }
    }
    else
    {
//this will be handled at taskflow level
      throw z;
     }
 }


3.  Taskflow Exception Handler
        Here We will discuss on session timeout and exception handling for at taskflow level by creating an Exception Handler

Task Flow changes
Create a router in your taskflow:


Add a condition which points to a method in backing bean. 
The method returns true if session expires and user is redirected to home/login page as needed.
And if method returns false, the user is redirected to default outcome - errorPage.

Mark the router as exception handler 



BEAN changes
Add the following method in your bean:

  public boolean isSessionExpired()
  {
    Exception e =
      ControllerContext.getInstance().getCurrentViewPort().getExceptionData();
    if (e != null && (e instanceof ViewExpiredException))
    {


// session  timeout case
      return true;
    }


// IF SOA is down or some other fault in SOA process

    else if (e != null &&
             (e instanceof ConnectException || e instanceof javax.xml.ws.WebServiceException ||
              e instanceof javax.xml.ws.soap.SOAPFaultException || e.toString().contains("Failed to access the WSDL")))
      putParameterinPageFlowScope("errorMessage",
                                  "Currently the system is in maintenance mode. Please try after sometime.");
    else
      putParameterinPageFlowScope("errorMessage",
                                  "Some unexpected error has occurred. Please try after sometime.");
    if (e != null)
    {
      StringWriter errors = new StringWriter();
      e.printStackTrace(new PrintWriter(errors));
      if(errors != null)
         putParameterinPageFlowScope("detailedException",errors.toString());
    }
    return false;
  }

Note:

In case where there is an exception other than ViewExpiredException(session timeout), write two parameters in request or pageFlowScope as written above:

·          Put Parameter in PageFlowScope("errorMessage", "Currently the system is in maintenance mode. Please try after sometime.");
·          Put Parameter in PageFlowScope ("detailedException",errors.toString());




Error Page
  
 <af:outputFormatted value="#{pageFlowScope.errorMessage}"/>
  <af:outputFormatted value="#{pageFlowScope.detailedException}" visible="false"/>

Note:

visible="false" makes sure the detailed exception is there in source of the page and user doesn`t see it.
You can see the same in page source.

You can add more conditions and messages in your bean method based on your scenarios like Content Server related exceptions, oim client,Bpm related etc.

 For any issue in implementation please comments.

Thanks



No comments:

Post a Comment