Saturday, January 31, 2015

Oracle ADF/Webcenter Portal:Builder(Spaces): Custom Error Handler

In order to display custom error messages in Oracle ADF/Webcenter:

1-extend the DCErrorHandlerImpl class and override the reportException like this:

public class CustomDCErrorHandlerImpl extends DCErrorHandlerImpl {
    public CustomDCErrorHandlerImpl() {
        this(true);
    }

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

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

        if (ex instanceof oracle.jbo.ValidationException) {
            System.err.println("**********************************************");
            System.err.println("Exception Message : " + ex);
            System.err.println("**********************************************");
            String msg = ex.getMessage();
            int i = msg.indexOf("JBO-25013");
               //When JBO-25013 Too many object match promary key exception occur.
            if (i > 0) {
                message = "Data must be unique.";
            }
        } else {
            message = "Unexpected Error."  ;
        }
            FacesContext ctx = FacesContext.getCurrentInstance();
            FacesMessage fm = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, "");
            ctx.addMessage(null, fm);
}

}

OR

public class CustomDCErrorHandlerImpl extends DCErrorHandlerImpl {
    public CustomDCErrorHandlerImpl() {
        this(true);
    }

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

    @Override
    public void reportException(DCBindingContainer dCBindingContainer, Exception exception) {
          if (exception.getMessage().contains("FK_SOMETHING")) {
            String message = JSFUtils.getStringFromBundle("FOREIGN_KEY_ERROR_MESSAGE");
            FacesContext ctx = FacesContext.getCurrentInstance();
            FacesMessage fm = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, "");
            ctx.addMessage(null, fm);
        }

}

Note: Of course if you want to use the second methodology, you will have to use a JSFUtils class to help you get the Messages bundle from the system to get the Custom messages based on current Locale.

2-After extending the class, register it to your application DataBindings.cpx:
In Application Tag, Insert your class path to "ErrorHandlerClass" attribute like this:

<Application xmlns="http://xmlns.oracle.com/adfm/application"
             version="11.1.1.64.93" id="DataBindings" SeparateXMLFiles="false"
             Package="com.mycompany.project" ClientType="Generic"
             ErrorHandlerClass="oracle.webcenter.errorhandling.CustomDCErrorHandlerImpl">

Now everything will work as expected for ADF and Webcenter Portal:Framework but not Portal Builder(Spaces) because of the different architecture between Spaces and ADF application, and the fact that your ADF taskflows are deployed as a shared library to use it in your Webcenter Portal:Builder(Spaces) even if your already registered your Custom Error Handler in the ADF Shared Library's Data Bindings, because Spaces will override this property with its Error Handler oracle.webcenter.webcenterapp.internal.view.error.WCErrorHandlerImpl.

To make this work, go to \Oracle\Middleware\Oracle_WC1\webcenter\modules\oracle.webcenter.spaces_11.1.1\oracle.webcenter.spaces.webapp.war\WEB-INF\lib\spaces-web.jar\oracle\webcenter\webcenterapp\bindings\DataBindings.cpx and replace WCErrorHandlerImpl Class path with your Custom one and restart all your domain.

Note:
a. Now you registered one Error Handler for all your portals.
b. The Custom Error handler must be in a package that is already registered in your extend.spaces.webapp.war(Will explain how to create an ADF Shared Library and use it in your Portal:Spaces in the next post.)