Monday, October 28, 2013

Oracle ADF Exception Handling Methods

1) Binding Layer : At binding layer, the exceptions can be either be handled for all the pages included in dataBinding.cpx file or for an individual page.

Handle exception of all the pages:

To handle binding layer exception for all the pages, extend the DCErrorHandlerImpl class and override the reportException method. Register this custom error handler class in DataBinding.cpx file under Application tag as follows:

ErrorHandlerClass="com.exception.handler.CustomErrorHandler "


public class CustomErrorHandler extends DCErrorHandlerImpl {

    private String[][] overrideExceptions = {{"oracle.jbo.JboException", "CUST_001","This is custom JBO exception message."}};

    public CustomErrorHandler (boolean setToThrow) {
        super(setToThrow);
    }

    public CustomErrorHandler () {
        this(true);
    }

    @Override
    public void reportException(DCBindingContainer bc, Exception ex) {
        BindingContext ctx = bc.getBindingContext();
        String err_code = null;
        if (ex instanceof TxnValException) {
            // Handle JBO-27023
            // Display exception message
        }
        if (ex instanceof oracle.jbo.DMLException) {
            // Handle JBO-26061
            // Display exception message        } else if (ex instanceof oracle.jbo.JboException) {
           // Display exception message
        } else {
            super.reportException(bc, ex);
        }
    }

    @Override
    protected boolean skipException(Exception ex) {
        // Override this method to skip any exception.
        return super.skipException(ex);
    }

    @Override
    public String getDisplayMessage(BindingContext context,
                                    Exception exception) {

        //Override this method to return custom error message
        return message;
    }
}

Handle exception of individual page:

To handle exception for a single page, create a CustomFacesPageLifeCycle class that extends FacesPageLifecycle. Now override the reportErrors method:

public void reportErrors(PageLifecycleContext pageLifecycleContext) {
        DCBindingContainer bc = (DCBindingContainer)pageLifecycleContext.getBindingContainer();
        if (bc != null) {
            ControllerContext context = ControllerContext.getInstance();
            ViewPortContext currentRootViewPort = context.getCurrentRootViewPort();
            Exception exceptionData = currentRootViewPort.getExceptionData();
            if (currentRootViewPort.isExceptionPresent()) {
                currentRootViewPort.clearException();

                FacesContext facesContext = FacesContext.getCurrentInstance();
                facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, exceptionData.getMessage(), null));
            }
}

Open the page definition file of the page for which exception is to be handled and add ControllerClass="com.exception.CustomFacesPageLifeCycle" in the pageDefinition tag.

2) Controller Layer : To handle exception at controller layer, there are following two ways:

Handle exception using task flow exception handler

The exceptions inside task flow, which are thrown by the method call activity used inside it, can be handled by marking bean method/jspx page as exception handler.

Handle exception using custom exception handler

If the exception is not handled by taskflow exception handler, then create custom exception handler as follow.

Create a CustomExceptionHandler class by extending  ExceptionHandler class and define the exception handling logic in handleException method.

public void handleException(FacesContext facesContext, Throwable throwable,
                                PhaseId phaseId) throws Throwable {
        String error_message;
        error_message = throwable.getMessage();


        // Handle the exception if required, Otherwise re-throw by using "throw throwable;"
}

In order to register this custom exception handler, create a folder named "services" inside .adf\META-INF and inside that folder create a text file with name "oracle.adf.view.rich.context.ExceptionHandler" having content as the path of CustomExceptionHandler file with package structure, like:

com.exception.handler.CustomExceptionHandler

3) Application Layer: In order to handle the exception at master application level, which is having multiple number of projects, create a custom application life cycle and register our custom exception handler.

First create custom exception handler class, CustomErrorHandler, that extends DCErrorHandlerImpl and override the reportException method. This is described in the post above.

Now create CustomFacesLifeCycle class that extends FacesPageLifecycle class and override prepareModel method:

    public void prepareModel(LifecycleContext lifecycleContext) {
        if (!(lifecycleContext.getBindingContext().getErrorHandler() instanceof
              CustomErrorHandler)) {
            lifecycleContext.getBindingContext().setErrorHandler(new CustomErrorHandler(true));
        }
        super.prepareModel(lifecycleContext);

    }

Now create a CustomADFPhaseListener class that extends ADFPhaseListener class and Override the createPageLifecycle method to return a new custom lifecycle as follows .

public class CustomADFPhaseListener extends ADFPhaseListener {
  protected PageLifecycle createPageLifecycle() {
    return new CustomFacesLifeCycle();
  }
}

Now register the CustomADFPhaseListener in the faces-config file, under Life Cycle tab.

Friday, February 1, 2013

Oracle ADF Read Images From Database Dynamically

Following is one of the way of displaying images from database dynamically and show on ADF page without using HTTP Servlet. The advantage of this method is that we don't require to create DB connection, create and execute query, which are required if we use servlet for displaying the images.

Following are the steps:

1) Create View Object : First create a view object based on table having images as blob column. The below viewObject is based on entityObject but should be created as read only without entity object.


2) Create Managed/Backing Bean: Create a bean file and write following code to read the blob content of image as byte array and convert that to encoded string. This string content will be used to display the image on page.

    public String getImageArray() {
            BlobDomain attribute = (BlobDomain)ADFUtils.evaluateEL("#{row.bindings.Image.inputValue}");
            try {
                byte[]   bytesEncoded = Base64.encode(attribute .getBytes(1L,(int)attribute.getLength()));
                imageArray= new String(bytesEncoded);
            } catch (Exception e) {
                e.printStackTrace();
            }
        return imageArray;
    }


The above code is using EL as #{row.bindings.Image.inputValue} since the data is shown under table.

3) Create Image Component: Drop the image attribute from datacontrol onto jspx page as outputText component just to create the binding of the image attribute. Alternatively we can go to binding tab of the page and add image attribute binding. Now add image component as follow:

           <af:image  source="data:image/png;base64,#{bean.imageArray}"
                          shortDesc="#{row.bindings.ImageName.inputValue}"
                          id="it1">
            </af:image>

4) Final Page: The above method will display the images as follow