Skip Headers
Oracle® Application Development Framework Developer's Guide For Forms/4GL Developers
10g Release 3 (10.1.3.0)
B25947-01
  Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
 
Next
Next
 

20.8 Handling and Displaying Exceptions in an ADF Application

Exceptions thrown by any part of an ADF application are also handled and displayed on the JSF page. By default, all exceptions thrown in the application are caught by the binding container. When an exception is encountered, the binding container routes the exception to the application's active error handler, which by default is the DCErrorHandlerImpl class. The reportException(BindingContainer, Exception) method on this class passes the exception to the binding container to process. The binding container then processes the exception by placing it on the exception list in a cache.If exceptions are encountered on the page during the page lifecycle, (for example, during validation), they are also caught by the binding container and cached, and are additionally added to FacesContext.

During the Prepare Render phase, the ADF lifecycle executes the reportErrors(context) method. This method is implemented differently for each view technology. By default, the reportErrors method on the FacesPageLifecycle class:

You can customize this default framework behavior. For example, you can create a custom error handler for exceptions, or you can change how the lifecycle reports exceptions. You can also customize how a single page handles exceptions.

20.8.1 How to Change Exception Handling

You can change the default exception handling by extending the default error handler, DCErrorHandlerImpl. Doing so also requires that you create a custom ADF lifecycle class that will call the new error handler during the Prepare Model phase.

You can also create a custom ADF lifecycle class to change how the lifecycle reports errors by overriding the reportErrors method.

If you only want to change how exceptions are created for a single page, you can create a lifecycle class just for that page.

To create a custom error handler:

  1. Create a class that extends the DCErrorHandlerImpl class.

  2. In the new class, override the public void reportException(DCBindingContainer, Exception) method.

    Example 20-9 shows the SRDemoErrorHandler Class that the SRDemo application uses to handle errors.

    Example 20-9 SRDemoErrorHandler Class

    public class SRDemoErrorHandler extends DCErrorHandlerImpl{
      /**
       * Constructor for custom error handler.
       * @param setToThrow should exceptions throw or not
       */
      public SRDemoErrorHandler(boolean setToThrow) {
        super(setToThrow);
      }
      /**
       * Overridden ADF binding framework method to customize the way
       * that Exceptions are reported to the client.
       * Here we set the "append codes" flag to false on each JboException
       * in the exception (and any detail JboExceptions it contains)
       * @param bc BindingContainer
       * @param ex exception being reported
       */
      public void reportException(DCBindingContainer bc, Exception ex) {
         //Force JboException's reported to the binding layer to avoid
         //printing out the JBO-XXXXX product prefix and code.
        disableAppendCodes(ex);
        super.reportException(bc, ex);
      }
      
      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]);
            }
          }
        }
      }
    }
    
    
  3. Globally override the error handler. To do this, you must create a custom page lifecycle class that extends FacesPageLifecycle. In this class, you override the public void prepareModel(LifecycleContext) method, which sets the error handler. To have it set the error handler to the custom handler, have the method check whether or not the custom error handler is the current one in the binding context. If it is not, set it to be. (Because by default the ADFBindingFilter always sets the error handler to be DCErrorHandlerImpl, your method must set it back to the custom error handler.) You must then call super.prepareModel.

    Example 20-10 shows the prepareModel method from the frameworkExt.SRDemoPageLifecycle class that extends the FacesPageLifecycle class. Note that the method checks whether or not the error handler is an instance of the SRDemoErrorHandler, and if it is not, it sets it to the new error handler.

    Example 20-10 PrepareModel Method

    public void prepareModel(LifecycleContext ctx) {
        if (!(ctx.getBindingContext().getErrorHandler() instanceof 
              SRDemoErrorHandler)) {
            ctx.getBindingContext().setErrorHandler(new SRDemoErrorHandler(true));
        }
        //etc
        super.prepareModel(ctx);
    }
    
    
  4. You now must create a new Phase Listener that will return the custom lifecycle. See the procedure "To create a new phase listener:" later in the section.

To customize how the lifecycle reports errors:

  1. Create a custom page lifecycle class that extends FacesPageLifecycle.

  2. Override the public void reportErrors(PageLifecycleContext) method to customize the display of error messages.

    See the SRDemo for the reportErrors() method, which is found in the frameworkExt.SRDemoPageLifecycle class. The method customizes the error handling by "pruning" exceptions from the list that the user cannot directly do anything to correct. In general, the errors being pruned out are the "wrapper exceptions" that are added by the ADF Business Components bundled exception mode. For information about the bundled exception mode, see Section 10.5.7, "Understanding Bundled Exception Mode".

  3. You now must create a new phase listener that will return the custom lifecycle.

To create a new phase listener:

  1. Extend the ADFPhaseListener class.

  2. Override the protected PageLifecycle createPageLifecycle () method to return a new custom lifecycle.

    Example 20-11 shows the createPageLifecycle method in the frameworkExt.SRDemoADFPhaseListener class.

    Example 20-11 CreatePageLifecycle Method in SRDemoADFPhaseListener

    public class SRDemoADFPhaseListener extends ADFPhaseListener {
      protected PageLifecycle createPageLifecycle() {
        return new SRDemoPageLifecycle();
      }
    }
    
    
  3. Register the phase listener in the faces-config.xml file.

    • Open the faces-config.xml file and select the Overview tab in the editor window. The faces-config.xml file is located in the <View_Project>/WEB-INF directory.

    • In the window, select Life Cycle and click New. Click Help or press F1 for additional help in registering the converter.

To override exception handling for a single page:

  1. Create a custom page lifecycle class that extends the FacesPageLifecycle class.

  2. Override the public void reportErrors(PageLifecycleContext) method to customize the display of error messages. For an example of overriding this method, see the procedure "To customize how the lifecycle reports errors:" earlier in this section.

  3. Open the page definition for the page. In the Structure window, select the page definition node. In the Property Inspector, enter the new class as the value for the ControllerClass attribute.

20.8.2 What Happens When You Change the Default Error Handling

When you create your own error handler, the application uses that class instead of the DCErrorHandler class. Because you created and registered a new lifecycle, that lifecycle is used for the application. This new lifecycle instantiates your custom error handler.

When an error is subsequently encountered, the binding container routes the error to the custom error handler. The reportException(BindingContainer, Exception) method then executes.

If you've overridden the reportErrors method in the custom lifecycle class, then during the Prepare Render phase, the lifecycle executes the new reportErrors(context) method.