Java EE applications such as those you build with Oracle Application Development Framework (Oracle ADF) are based on a layered architecture following the model-view-controller paradigm. In such a layered architecture, each layer can become the origin of an application error that requires handling. As a consequence, error handling should be designed and implemented in all application layers.
Error handling is a large knowledge area, and complete coverage of the topic exceeds the Oracle Magazine article format. To fit the available format, this article covers an overview of error handling in Oracle ADF, followed by hands-on instructions on how to implement custom error handlers on the Oracle ADF Controller layer.
As shown in Figure 1, the Oracle ADF application architecture consists of four layers: business service, Model, Controller, and View. Errors can occur in any of these application layers.
Figure 1: Oracle ADF error handling architecture
The business service layer contains the business logic and handles the datasource interaction required for querying data and persisting changes. This layer can produce validation errors—including database errors—and informational warnings.
The Oracle ADF Model (referred to in the sample application as ADFm) layer consists of two parts, the business-service-specific data control that connects Oracle ADF to data bindings and services such as Oracle ADF Business Components, Pojo, Web services, or Enterprise JavaBeans (EJB). The data binding definition for a view is defined in metadata and is referred to as the “ADF Binding Layer” at runtime. The responsibility of the binding layer is to connect user interface components with the data and business logic exposed by the business service through the data control. Binding errors occur in cases of row key issues, client component binding failures, malformed expression language (EL) expressions, and so on. If validation rules are defined on a binding container, validation errors can also occur.
The Oracle ADF Controller (referred to in the sample application as ADFc) layer handles application navigation and the client request lifecycle. Oracle ADF Controller errors occur in case of metadata configuration problems, missing user authorization, mismatches in task flow transaction settings, invalid input parameter objects, and so on.
The Oracle ADF View (referred to in the sample application as ADFv) layer, represented by Oracle ADF Faces in Oracle ADF, provides a set of UI components for building GUIs and temporarily holding user data input until the data is written to the model. View layer errors include client-side validation problems, datatype conversion failure, view expiry, EL reference problems, and so on.
Figure 1 shows the various Oracle ADF architecture layers introduced earlier. Using Oracle ADF, applications facilitate the Oracle ADF Model for querying or updating data exposed through business services such as Oracle ADF Business Components. Errors that occur in the business service during data query or update propagate to the Oracle ADF Model if the business service doesn’t handle them by, for example, using a Java try/catch block surrounding validation or business logic.
The Oracle ADF Model error handler and Oracle ADF Controller error handler activity defined for a task flow are central in the overall Oracle ADF application error handling.
Errors that occur in a context outside of the Oracle ADF Model or during the JavaServer Faces (JSF) “render response” phase must be handled manually by developers, who can use a try/catch block in Java or implement a custom Oracle ADF Controller exception handler class.
As a last resort, you can configure the web.xml file so that specific error types and HTTP error codes are handled by the Java EE Servlet container. In Oracle ADF, your best option for handling application errors is to ensure that the business service is always accessed through the Oracle ADF Model layer. Direct access of the business service from managed beans should be banned in your Oracle ADF developer guidelines.
The Oracle ADF base exception class, oracle.jbo.JboException, extends java.lang.RuntimeException. JboException or any of its subclasses can be called from anywhere in an application without the need to declare the call as part of a method signature. Developers who want to build and call custom exceptions should extend JboException or one of its subclasses for best integration with Oracle ADF.
To follow the hands-on steps in this article, you’ll need the studio edition of Oracle JDeveloper 11g Release 2 (18.104.22.168), available as a free download on Oracle Technology Network. You also need access to an Oracle Database instance with an unlocked HR schema. Get started by downloading the o23adf-1896561.zip sample application and unzipping the file.
To prepare for the hands-on steps, change the database connection used by the Oracle ADF Business Components Model project to point to your HR database schema:
Launch Oracle JDeveloper 11g Release 2. From the Oracle JDeveloper menu bar, select File -> Open, and then navigate to the directory containing the unpacked sample application.
Open the ErrorHandling folder, select the ErrorHandling.jws file, and click Open. The workspace opens.
Select View -> Database -> Database Navigator, and expand the ErrorHandling node to display the hrconn node.
Right-click hrconn, and select Properties from the context menu. Edit the database connection information to work with your setup. Test the changes, and click OK.
As another preliminary task, start the Oracle WebLogic Server instance integrated with Oracle JDeveloper. To start the Oracle WebLogic Server instance, select Run -> Start Server Instance (IntegratedWebLogicServer).
If this is the first time you’ve run the integrated Oracle WebLogic Server instance, a Create Default Domain dialog box will open. Create a password for the default Oracle WebLogic Server domain, and select an address from those listed for Listen Address. For example, choose localhost rather than leaving the address empty.
Click OK to save the password and address, create the default domain, and configure it for Oracle ADF.
The sample application contains five Oracle JDeveloper projects:
ADfErrorHandlingUtil contains the Oracle ADF Controller and Oracle ADF Model error handler code you will use during the hands-on steps in this article and is referenced as a dependency in other projects.
BoundedTaskFlowUtil contains a task flow template for you to use to configure a method activity as an error handler to be used by all bounded task flows in the sample application.
Model contains view objects for querying department and dependent employee data. It exposes client methods on the application module to simulate exceptions thrown when you’re working with Oracle ADF. The Employees entity has a validation rule defined to prevent the last name field from being updated to King.
UnboundedTaskFlowUtil is precreated for you and contains an unbounded adfc-config.xml file with an error handler activity.
ViewController contains the task flows and the binding context to which you will add error handling in the hands-on steps.
Disclaimer: For your convenience, all projects in this sample application are created in a single Oracle JDeveloper workspace and all bounded task flows are in one ViewController project. Note that this is not necessarily best-practice design.
Run the sample application by selecting the Oracle JDeveloper Application (Navigator) tab, selecting View Controller -> Web Content -> pages -> DeptEmp.jsf, right-clicking the DeptEmp.jsf file, and choosing Run from the context menu.
When the application starts, click Next twice to display information for department 30. Figure 2 shows the sample application running in a browser and the result for department 30.
Figure 2: Sample application screen for department 30
The department’s UI and its command buttons are located in the unbounded task flow. The employee detail table and its buttons are within a bounded task flow. The Edit Employee button navigates from the bounded task flow to a subtask flow showing an edit form.
Note that command buttons with ADFc in their labels invoke a method activity for throwing an exception when the business service is being accessed through the Oracle ADF Binding Layer. Oracle ADF Controller exceptions are handled by the Oracle ADF Controller exception handler. Buttons with ADFm in their labels access the business service directly through the Oracle ADF Binding Layer to demonstrate error handling through the Oracle ADF Model error handler.
To explore the default error handling, follow these steps in the application running in your browser:
Click ADFc Custom Exception<—below the department data—to see the default error handling in Oracle ADF Controller unbounded task flows if no exception handler is set up.
Click ADFm Throw Nested Exception to see how the Oracle ADF Model error handler, which is configured by default, handles exceptions in the business service (and so much more nicely than when no exception handler is set up).
Click Edit Employee to navigate to the edit form for the currently selected employee ID, which should be 114 (Den Raphealy). Change the Email field from DRAPHAELY to SKING, and click Commit. The error you see is a unique key constraint validation thrown by the database. The error propagates from the business service to the binding layer for handling.
Change the value back to DRAPHAELY, and click Commit.
Click ADFm Custom Exception to see a custom application exception handled by the Oracle ADF Model error handler.
Click ADFc JboException to see how business service errors propagate to the Oracle ADF Controller if no error handling is set up.
Click Return to Browse View.
Note: All exceptions other than validation and database constraint exceptions in this sample application are generated by code in the AppModuleImpl file, located in the oramag.marapr.thirteen.sample.model.bc.services package of the Model project.
As you have seen when running the sample, the display of Oracle ADF Controller errors is not user-friendly or localized. This is because no error handler has been set up. In the following steps, you will configure a task flow activity as the error handler for the unbounded task flow.
In the Oracle JDeveloper Application Navigator, expand UnboundedTaskFlowUtil and select Web Content -> Page Flows -> adfc-config. Right-click adfc-config, and choose Open from the context menu. The unbounded task flow configuration file contains a method activity—UnboundedTaskFlowErrorHandler— configured as an error handler (indicated by the exclamation mark overlay icon). The method activity references the showAdfcErrorMessageInDialog method of the AdfcSampleErrorHandlerImpl class in ADfErrorHandlingUtil to show a dialog box for displaying controller errors.
Right-click the UnboundedTaskFlowUtil node, and choose Deploy -> UnboundedTaskFlowUtilLib from the context menu to deploy the Oracle ADF library containing the error handler.
Click Finish (because you are not making changes to the deployment directory).
In the Application Navigator, select the ViewController project.
Choose View -> Resource Palette. In the Resource Palette, create a new file system connection by clicking the menu button with the folder icon and choosing New Connection -> File System from the menu (as shown in Figure 3).
Figure 3: Creating a new file system connection
Name the new connection Unbounded Task Flow Error Handler.
Click Browse to navigate to and select the deploy folder—located in the ErrorHandling -> UnboundedTaskFlowUtil folder—in the directory to which you unzipped the downloaded sample zip file.
Click Select and then OK.
In the Resource Palette, expand the IDE Connections panel and then the File System -> Unbounded Task Flow Error Handler node.
With the ViewController project selected in the Application Navigator, right-click the UnboundedTaskFlowUtilLib.jar file, displayed in the Resource Palette under the Unbounded Task Flow Error Handler node, and choose Add to Project from the context menu.
Click Add Library in the dialog box to configure the library for the ViewController project.
Save your work, and test the application by selecting View Controller -> Web Content -> pages -> DeptEmp.jsf, right-clicking the DeptEmp.jsf file, and choosing Run from the context menu. Try the command buttons that have ADFc in the labels to see the difference in the behavior.
At any time in Oracle ADF, there is only one unbounded task flow instance. In cases in which there are multiple adfc-config.xml files in the class path for an application, the Oracle ADF Controller merges them into a single configuration at runtime.
The Oracle ADF library you just added to the ViewController project contains an adfc-config.xml file with a method activity as an exception handler. At application runtime, this exception handler is added to the application’s unbounded task flow.
Containing all exception handler activity in the unbounded task flow seems to handle all controller exceptions in the sample application well, in that it displays a user-friendly error message. Still, there is an issue to fix. When you simulate an exception in the bounded task flow by clicking ADFc Custom Exception below the employee table, the error displays in the custom dialog box. The error handling, however, is not in the bounded task flow but in the unbounded task flow, which means that the bounded task flow is left in an unpredictable state, because application focus now is on the unbounded task flow. To avoid this and follow Oracle ADF best practices, you should define error handler activities in all bounded task flows so problems can be handled locally inside a task flow. Details on how to configure exception handler activities for bounded task flows are in the next section.
Unlike in unbounded task flows, it is not enough for bounded task flows to add an Oracle ADF library with an exception handler activity to the class path. Instead, the activity must be configured in each task flow. To simplify the configuration task, this hands-on section uses a task flow template containing the exception handler activity and references it from the two bounded task flows in the sample.
In the Oracle JDeveloper Application Navigator, expand the BoundedTaskFlowUtil project and select the Web Content -> Page Flows -> btf-error-handler-template bounded task flow template file. Right-click the file, and choose Open from the context menu. The task flow template contains a method activity—BtfErrorHandler—that references the showAdfcError MessageInDialog method of the AdfcSampleErrorHandlerImpl class in the ADfErrorHandlingUtil project to display controller errors in a dialog box.
On the btf-error-handler-template.xml tab, select the Diagram tab , select the BtfErrorHandler method activity image, and click the red exclamation mark (Mark Exception Handler) in the diagram toolbar. This configures the method activity as an exception handler.
To deploy the bounded task flow template with the error handler activity in the Application Navigator, right-click the BoundedTaskFlowUtil project node and choose Deploy -> BoundedTaskFlowUtilLib from the context menu. The Oracle ADF library has been predefined for this sample.
Click Finish in the dialog box (because you are not making changes to the deployment directory).
In the Application Navigator, select the ViewController project.
Choose View -> Resource Palette to display the Resource Palette panel.
In the Resource Palette, expand the IDE Connection accordion tab and right-click the File System node.
Select New File System Connection from the menu, and name the new connection Bounded Task Flow Error Handler.
Click Browse to navigate to and select the deploy folder—located in the ErrorHandling -> BoundedTaskFlowUtil folder—in the directory to which you unzipped the downloaded sample zip file.
Click Select and then OK.
In the Resource Palette -> IDE Connections panel, expand the File System -> Bounded Task Flow Error Handler node.
With the ViewController project selected in the Application Navigator, right-click the BoundedTaskFlowUtilLib.jar file—located under the Bounded Task Flow Error Handler node in the Resource Palette—and choose Add to Project from the context menu.
Click Add Library in the opened dialog box to add the Oracle ADF library with the bounded task flow exception handler for the ViewController project.
In the Application Navigator, expand the ViewController -> Web Content -> Page Flows -> bounded-tf node.
Select the browse-employees-task-flow bounded task flow, and select View -> Structure to open the Structure window (if it is not already open).
In the Structure window, expand the ADF Task Flow node and select the task-flow-definition child node.
Select View -> Property Inspector, and navigate to the Document property under the Based on Template header.
Set the Document property value to
Note: /WEB-INF/btf-error-handler-template.xml is the name of the template document defined in the BoundedTaskFlowUtil project. There is no option yet in Oracle JDeveloper for a project to browse configured Oracle ADF libraries for the names of contained documents. Therefore, this configuration is manual for existing bounded task flows. If you build a new bounded task flow, you have the option—in the process of task flow creation—to select a template, in which case this configuration is automated for you.
Edit the Based on Template ID property, selecting the btf-error-handler-template entry from the list. (You must click in the Based on Template ID field for the select list to appear.) Before configuring the exception handler on the second bounded task flow in the sample, run the application. Select View Controller -> Web Content -> pages -> DeptEmp.jsf, right-click DeptEmp.jsf, and choose Run from the context menu.
When the sample application appears in the browser, click Edit Employee (below the employee table) to navigate to the bounded task flow containing the edit form.
In the edit view, click ADFc JboException and note how the edit form task flow is abandoned and focus is put back on the employee bounded task flow. Task flows with no defined error handling are closed when an exception occurs and is passed on to the calling task flow. You can avoid this by configuring an exception handler activity in all bounded task flows.
Repeat steps 14 through 19 for the edit-employee-task-flow bounded task flow in the ViewController project, and rerun the sample application.
Save your work.
Note: Bounded task flows don’t necessarily need to share the same error handler activity. Instead, each bounded task flow can have its own error handler routine defined. Also, there is no rule that errors must be displayed in a dialog box as demonstrated in this sample application. You can, for example, configure a router activity as an error handler to handle exceptions differently, according to their specific type or error codes.
The Oracle ADF Model error handler is configured in the Oracle ADF Binding context and handles errors that occur when the business service is accessed through the Oracle ADF Binding Layer. The default implementation class is DCErrorHandlerImpl—you’ve seen it in action earlier when running the sample application and clicking one of the buttons prefixed with ADFm in the label.
The Oracle ADF Model error handler is central in Oracle ADF error handling, and by default it re-raises only exceptions handled by the controller of the Oracle ADF Faces view layer. It also, however, removes the outer exception from bundled exceptions to avoid displaying duplicate error messages. In a production environment, there is a lot more you may want to do with exceptions, such as suppressing specific exceptions, changing error messages, or adding logging and incident reporting.
To address these requirements, you can customize the Oracle ADF error handler as shown in the following steps.
In the Application Navigator, expand the ViewController -> Application Sources node.
Expand oramag.marapr.thirteen.sample.view, and select the DataBindings.cpx file.
In the Structure window, select the DataBindings node.
In the Property Inspector (for DataBindings properties), find the ErrorHandlerClass property and click the arrow icon next to it.
In the Match Class Name search field in the opened dialog box, type AdfmSampleErrorHandlerImpl.
Select the class found in the Matching Classes box, and click OK to configure it as the exception handler.
The AdfmSampleErrorHandlerImpl error handler class is defined in the ADfErrorHandlingUtil project and, for demonstration purposes, appends a message prefix—Oracle Magazine Error Handler:—to the error messages. In addition, the error handler removes the ORA-xxxx message for constraint violations in the sample application.
See Oracle Fusion Middleware Fusion Developer’s Guide for Oracle Application Development Framework 11g Release 2 (22.214.171.124.0) for detailed information about methods you can override in your custom error handler and how to do it.
Run the sample application. In the Application Navigator, select View Controller -> Web Content -> pages -> DeptEmp.jsf, right-click DeptEmp.jsf, and choose Run from the context menu.
Repeat steps 1 through 8 from the “Sample Application Overview” section to observe the custom error handling.
There is only one Oracle ADF Model error handler active for an Oracle ADF application. For this reason, a custom Oracle ADF Model error handler should be configured only in the DataBindings.cpx file of the application and never in bounded task flows deployed as Oracle ADF libraries.
This article stepped you through the configuration of a custom error handler activity in Oracle ADF task flows and the customization of the default binding error handler. Error handling is a large knowledge area—follow up by reading more about it in the product documentation and blog entries listed in “Next Steps.”
LEARN more about Oracle ADF
READ more about error handling
Photography by Stefan Stefancik, Unsplash