A few months back I had blogged about some advanced Fault Handling concepts that can be implemented in Oracle SOA Suite 11g by leveraging the in build policy based fault framework, using custom JAVA Action to implement a fault condition and the use of SOA Suite API’s to retry them.
The full blog post can be read here
Unfortunately the same policy based fault management cannot be used for components in a composite application that are based on BPMN. The same policy based fault management will be available in some future versions of Oracle BPM Suite.
This article will try to explain how we can have a fault and exception handling defined for a BPM process in our composite application.
Consider a very basic BPMN process to approve the credit application for an individual. The process is exposed as a web service with an asynchronous callback. It takes the applicant’s Social Security Number and processes the credit approval process for him.
The business process take the applicant’s SSN and retrieves his credit history from a web service interface. The details of his credit history are presented to a credit approval clerk who can either approve or reject it. Upon rejection the process throws a custom business exception and is terminated. If the credit approval clerk approves the application the process is ended gracefully. Quite simple. So let us get started.
The following visio diagram explains the simple use case et all.
The above process needs to have a runnable implementation. We can design and deploy the same process in Oracle JDeveloper. The process inside JDeveloper looks like this.
Use the XML Schema below to create a Business Object called PersonalInformation inside the BPM Business Catalog. The business process is instantiated with a message start event. Use this business object as the input argument for the Start event.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.soatechnologies.blog/pi" targetNamespace="http://www.soatechnologies.blog/pi" elementFormDefault="qualified"> <xsd:element name="ApplicantInformation"> <xsd:complexType> <xsd:sequence> <xsd:element name="firstName" type="xsd:string"/> <xsd:element name="lastName" type="xsd:string"/> <xsd:element name="ssn" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="CreditApprovalResponse"> <xsd:complexType> <xsd:sequence> <xsd:element name="creditRating" type="xsd:string"/> <xsd:element name="isDefaulter" type="xsd:boolean"/> <xsd:element name="noOfDefaults" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>
Add a variable called applicationInformation of type Process Data Object and assign the value of the input argument to it.
The complete JDeveloper project can be downloaded from the link here. Import it and see how the rest of the process has been created.
The Get Credit History service task in the project has a boundary event attached to it.
Boundary events can be of Error, Timer or Message type and are triggered if the activity to which they are attached is not yet completed. They are very useful for Exception and Interruption Handling.
Our process in this example uses an Error Boundary Event that catches Remote Fault for the service task i.e for instance faults arising out of remote endpoint being unavailable.
You can even attach a Timer Boundary Event to any activity or SubProcess. If the activity or the Subprocess doesn’t complete within the Time defined in the timer event, the process triggers in the direction to which the boundary event is wired.
The wire from this Error Boundary Event is drawn to the Handle Service Remote Fault Subprocess that introduces a wait and loops it back to the Service Task. Doing this ensures that if an error occurs due to service unavailability the process retries by itself before terminating.
The number of retries can be controlled by defining a counter for the Service task and adding an exclusive gateway in the Remote fault Handling Subprocess.
Once the activity has been retried for the maximum number of allowed time the process is terminated.
Another thing that every BPM process needs to have is define and handle Business Faults.
Business Exceptions can be defined in the Business Catalogue component inside a BPM project.
Business Exceptions created thus can now be thrown from the process if in case any business scenario fails to meet. In the present example let us throw an ApprovalException if the approval clerk rejects the credit application request.
This can be achieved by throwing and catching Intermediate Events inside the process flow. Drag an Error Event of type Error from the BPM Component Palette in the process canvass.
The Check Manual Response gateway evaluates the response of the approval clerk and forks the process into two paths. Connect the sequence that evaluates to a “REJECT” outcome to this error event.
Now that we have thrown a custom business exception we need to define a way in our process to catch and handle it.
In Oracle BPM 11g we can create Event Subprocesses that are invoked when an Event that they are listening to are thrown.
You can drag an Event Subprocess from the Activities pane of the BPM Component Palette. The event trigger for start event of the Event sub process is changed to “Error” which means it would Catch an Error event to initialize its flow. From the list of Exceptions select the custom business exception that was just created.
The Event Subprocess is in itself a mini process having its own Start, End and intermediate activities. Depending upon preference we can choose to either create a Manual Task to allow user to take a look at the Custom Exception and may be handle it offline.
Service Activities to log the exception record to File/DB or JMS can also be used or we can simple choose the FYI Task to notify users.
Similarly create another Event Subprocess that catches all other exceptions inside the process (something like a Catch All branch)
The basic process design and fault handling is complete now. Deploy this composite application now on a running SOA Server where we will run a few scenarios to validate whether the process behaves as expected.
Scenario 1 : Application is Rejected by Approval Clerk
The CreditApproval business process has a message start event. It can be invoked as a webservice. To test it as a webservice we can login to the EM console, locate the composite application in the partition where we deployed it and test it.
The composite instance lands up in the Running state as it is waiting in the inbox of the approval clerk. Login to the custom worklist application and reject the instance.
As we have designed the process to throw and catch a custom business exception in case an application is rejected the process instance during runtime does exactly that.
The business exception is caught and thrown by the Event Sub process. See the process instance flow to see how the instance completes its execution.
Scenario 2 : The Get Credit History web service is Unavailable
If you recall we had added a Boundary event to the Service Task. The boundary event will catch Remote Fault (if any) occurring in the service task activity and call the subprocess to decide whether a retry is needed or not. The maximum retry limit is set to a constant value of 3 here. Depending upon the number of times the Service Task has been invoked the subprocess either loops the instance back to the service task activity or terminates it (in case Retries are exhausted)
If the end point doesn’t come up within the defined retries the process terminates.
On the contrary if the Web Service endpoint become available the process instance is completed.
This article demonstrates a basic fault handling approach that can be employed while designing business processes in Oracle BPM Suite 11g.
All the artifacts used in this article can be downloaded from here.