|Oracle® BPEL Process Manager Developer's Guide
Part Number B28981-03
This chapter contains the following topics:
This chapter uses an example of a credit rating service returning a negative credit message instead of a credit rating number. You also learn how to add a fault handler to a BPEL process to handle the message.
See Also:The following samples:
Fault handlers define how the BPEL process responds when the Web services return data other than what is normally expected (for example, returning an error message instead of a number). An example of a fault handler is where the Web service normally returns a credit rating number, but instead returns a negative credit message.
Figure 8-1 shows how a fault handler sets the credit rating variable at
Figure 8-1 Fault Handling
The following code segment defines the fault handler for this operation:
<faultHandlers> <catch faultName="services:NegativeCredit" faultVariable="crError"> <assign name="crin"> <copy> <from expression="-1000"> </from> <to variable="input" part="payload" query="/autoloan:loanApplication/autoloan:creditRating"/> </copy> </assign> </catch> </faultHandlers>
faultHandlers tag contains the fault handling code. Within the fault handler is a
catch activity, which defines the fault name and variable, and the copy instruction that sets the
creditRating variable to
When you select Web services for the BPEL process, determine the possible faults that may be returned and set up a fault handler for each one.
The Business Process Execution Language for Web Services Specification defines the following standard faults in the namespace of
Standard faults are defined as follows:
Typeless, meaning they do not have associated
Not associated with any WSDL message
Caught without a fault variable:
A BPEL fault has a fault name called a
Qname (name qualified with a namespace) and a possible
messageType. There are two categories of BPEL faults:
Business faults are application-specific faults that are generated when there is a problem with the information being processed (for example when a social security number is not found in the database). A business fault occurs when an application executes a throw activity or when an invoke activity receives a fault as a response. The fault name of a business fault is specified by the BPEL process. The
messageType, if applicable, is defined in the WSDL. A business fault can be caught with a
faultHandler using the
faultName and a
<catch faultName="ns1:faultName" faultVariable="varName">
Run-time faults are the result of problems within the running of the BPEL process or Web service (for example, data cannot be copied properly because the variable name is incorrect). These faults are not user-defined, and are thrown by the system. They are generated if the process tries to use a value incorrectly, a logic error occurs (such as an endless loop), a SOAP fault occurs in a SOAP call, an exception is thrown by Oracle BPEL Server, and so on.
Oracle BPEL Server includes several run-time faults. These faults are included in the
http://schemas.oracle.com/bpel/extension namespace. These faults are associated with the
RuntimeFaultMessage. The following WSDL file defines the
<?xml version="1.0" encoding="UTF-8" ?> <definitions name="RuntimeFault" targetNamespace="http://schemas.oracle.com/bpel/extension" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/"> <message name="RuntimeFaultMessage"> <part name="code" type="xsd:string" /> <part name="summary" type="xsd:string" /> <part name="detail" type="xsd:string" /> </message> </definitions>
RuntimeFaultMessage) is used when catching the fault, the fault code can be queried from the
faultVariable, along with the fault summary and detail.
bindingFault is thrown inside an activity if the preparation of the invocation fails. For example, the WSDL of the process fails to load. A
bindingFault is not retryable. This type of fault usually must be fixed by human intervention. Table 8-1 describes the fault codes.
Table 8-1 bindingFault Fault Codes
|Fault Code||Description of Fault|
||The processing party found an invalid namespace for the SOAP envelope element.|
||An immediate child element of the SOAP header element that was either not understood or not obeyed by the processing party contained a SOAP
||Generic error on the client side|
||Input message part number mismatch|
||Output message part number mismatch|
||Input message part type error|
||Output message part type error|
||Generic error on the server side|
||Server is up, but there is no service|
||Request is missing the HTTP SOAP action|
||Request is not authenticated|
||Request is not authorized|
remoteFault is also thrown inside an activity. It is thrown because the invocation fails. For example, a SOAP fault is returned by the remote service. A
remoteFault can be configured to be retried. Table 8-2 describes the fault codes.
replayFault replays the activity inside a scope. At any point inside a scope, this fault is migrated up to the scope. Oracle BPEL Server then re-executes the scope from the beginning.
BPEL run-time faults can be caught as a named BPEL fault. The
remoteFault can be associated with a message. This enables the
faultHandler to get details about the faults.
The following procedure shows how to use the provided examples to generate a fault and define a fault handler to catch it. In this case, you modify a WSDL file to generate a fault, and create a catch attribute to catch it.
RuntimeFault.wsdl into your process WSDL (located under the
Declare a variable with
Catch it using
<catch faultName="bpelx:remoteFault" | "bpelx:bindingFault" faultName="varName">
catchAll activity is provided to catch possible faults. However, BPEL does not provide a method for obtaining additional information about the captured fault. Use the
getFaultAsString() XPath extension function to obtain additional information.
<catchAll> <sequence> <assign> <from expression="bpelx:getFaultAsString()"/> <to variable="faultVar" part="message"/> </assign> <reply faultName="ns1:myFault" variable="faultVar" .../> </sequence> </catchAll>
The scope activity provides a container and a context for other activities. A scope provides handlers for faults, events, and compensation, as well as data variables and correlation sets. Using a scope activity simplifies a BPEL flow by grouping functional structures together. This allows you to collapse them into what appears to be a single element in Oracle JDeveloper.
The following code example shows a scope activity. In this case, the process for getting a credit rating based on a customer's social security number has been placed inside a scope named
getCreditRating. This identifies functional blocks of code and sets them apart visually. In Oracle JDeveloper, you can collapse the activities contained inside the scope into a single visual element, or expand them when necessary.
<scope name="getCreditRating"> <variables> <variable name="crError" messageType="services:CreditRatingServiceFaultMessage"/> </variables> <assign name="assign-2"> <copy> <to variable="input" part="payload" query="/autoloan:loanApplication/autoloan:creditRating"/> </copy> </assign> </sequence> </scope>
To add a scope activity:
Click and drag a scope activity into the BPEL process diagram.
Open the scope by double-clicking it or by single-clicking the + sign.
Drag activities from the Component Palette to build the function within the scope.
See Also:The following documentation for examples of creating scope activities in Oracle JDeveloper:
A BPEL application can generate and receive fault messages. The
throw activity has three elements: its name, the name of the
faultName, and the
faultVariable. If you add a
throw activity to your BPEL process, it automatically includes a copy rule that copies the fault name and type into the output payload. The fault thrown by a
throw activity is internal to BPEL. You cannot use a
throw activity on an asynchronous process to communicate with a client. Here is a code sample of a
throw activity, which includes the fault elements, name, and partner link of the service to which the BPEL process sends the fault, and the copy rule that packages the message:
<throw name="delay" faultName="fault-1" faultVariable="fVar"/> <invoke name="invokeStockQuoteService" partnerLink="StockQuoteService"/> <assign> <copy> <from variable="response" part="result" query="/result"/> <to variable="output" part="payload" query="/tns:result"/> </copy> </assign>
See Also:The following documentation for examples of creating throw activities:
A BPEL process can send a fault to another application to indicate a problem, as opposed to throwing an internal fault. In a synchronous operation, the reply activity can return the fault. In an asynchronous operation, the invoke activity performs this function.
The syntax of a
reply activity that returns a fault in a synchronous interaction is as follows:
<reply partnerlinke="partner-link-name" portType="port-type-name" operation="operation-name" variable="variable-name" (optional) faultName="fault-name"> </reply>
Always returning a fault in response to a synchronous request is not very useful. It is better to make the activity part of a conditional branch, where the first branch is executed if the data requested is available. If the requested data is not available, then the BPEL process returns a fault with this information.
In an asynchronous interaction, the client does not wait for a reply. The reply activity is not used to return a fault. Instead, the BPEL process returns a fault using a callback operation on the same port type that normally receives the requested information, with an invoke activity.
If a fault is not handled, it creates a faulted state that migrates up through the application and can throw the entire process into a faulted state. To prevent this, contain the parts of the process that have the potential to receive faults within a scope. As described earlier, the scope activity includes fault handling capabilities. The catch activity works within a scope to catch faults and exceptions before they can throw the entire process into a faulted state.
You can use specific fault names in the catch activity to respond in a specific way to an individual fault. To catch any faults that are not already handled by name-specific catch activities, use the catchAll activity.
See Also:The following documentation for examples of creating fault handling:
There is often a need to use an activity that does nothing. An example is when a fault must be caught and suppressed. In this case, you can use the
empty activity to insert a no-op instruction into a business process. The syntax to use an
empty activity is as follows:
<empty standard-attributes> standard-elements </empty>
catchAll is selected, the fault is not caught by the current scope and is rethrown to the immediately enclosing scope. If the fault occurs in (or is rethrown to) the global process scope, and there is no matching fault handler for the fault at the global level, the process terminates abnormally. This is as though a
terminate activity (described in "Using the Terminate Activity to Stop a Business Process Instance") had been performed.
Consider the following example:
<faulthandlers> <catch faultName="x:foo"> <empty/> </catch> <catch faultVariable="bar"> <empty/> </catch> <catch faultName="x:foo" faultVariable="bar"> <empty/> </catch> <catchAll> <empty/> </catchAll> </faulthandlers>
Assume that a fault named
x:foo is thrown. The first
catch is selected if the fault carries no fault data. If there is fault data associated with the fault, the third
catch is selected if the type of the fault's data matches the type of variable
bar. Otherwise, the default
catchAll handler is selected. Finally, a fault with a fault variable whose type matches the type of
bar and whose name is not
x:foo is processed by the second
catch. All other faults are processed by the default
Compensation occurs when the BPEL process cannot complete a series of operations after some of them have already completed, and the BPEL process must backtrack and undo the previously completed transactions. For example, if a BPEL process is designed to book a rental car, a hotel, and a flight, it may book the car and the hotel and then be unable to book a flight for the right day. In this case, the BPEL flow performs compensation by going back and unbooking the car and the hotel.
You can invoke a compensation handler by using the compensate activity, which names the scope for which the compensation is to be performed (that is, the scope whose compensation handler is to be invoked). A compensation handler for a scope is available for invocation only when the scope completes normally. Invoking a compensation handler that has not been installed is equivalent to using the empty activity (it is a no-op). This ensures that fault handlers do not have to rely on state to determine which nested scopes have completed successfully. The semantics of a process in which an installed compensation handler is invoked more than once are undefined.If an invoke activity has a compensation handler defined inline, then the name of the activity is the name of the scope to be used in the compensate activity. The syntax is as follows:
<compensate scope="ncname"? standard-attributes> standard-elements </compensate>
The ability to explicitly invoke the compensate activity is the underpinning of the application-controlled error-handling framework of Business Process Execution Language for Web Services Specification. You can use this activity only in the following parts of a business process:
In a fault handler of the scope that immediately encloses the scope for which compensation is to be performed.
In the compensation handler of the scope that immediately encloses the scope for which compensation is to be performed.
If a scope being compensated by name was nested in a loop, the BPEL process invokes the instances of the compensation handlers in the successive iterations in reverse order.
If the compensation handler for a scope is absent, the default compensation handler invokes the compensation handlers for the immediately enclosed scopes in the reverse order of the completion of those scopes.
The compensate form, in which the scope name is omitted in a compensate activity, explicitly invokes this default behavior. This is useful when an enclosing fault or compensation handler must perform additional work, such as updating variables or sending external notifications, in addition to performing default compensation for inner scopes. The compensate activity in a fault or compensation handler attached to the outer scope invokes the default order of compensation handlers for completed scopes directly nested within the outer scope. You can mix this activity with any other user-specified behavior except for the explicit invocation of the nested scope within the outer scope. Explicitly invoking a compensation for such a scope nested within the outer scope disables the availability of default-order compensation.
The terminate activity immediately terminates the behavior of a business process instance within which the terminate activity is performed. All currently running activities must be terminated as soon as possible without any fault handling or compensation behavior. The terminate activity does not send any notifications of the status of a BPEL process. If you are going to use the terminate activity, first program notifications to the interested parties.
The syntax for the
terminate activity is as follows:
<terminate standard-attributes> standard-elements </terminate>
See Also:The following documentation for examples of creating terminate activities:
The ResilientDemo sample demonstrates failover fault handling and retry fault handling. Failover allows multiple service implementations to be configured for a partner link. If a retryable run-time fault occurs, then the server tries other service implementations. In retry fault handling, the server retries based on a specified retry interval and retry count. Another kind of fault, a binding fault, can occur if the Web service has been upgraded and the interface has changed. In the ResilientDemo sample, when a binding fault occurs, the document is placed in a dead letter queue using a JMS service. The diagram of
ResilientFlow.bpel is shown in .
Figure 8-2 Diagram Window of ResilientFlow.bpel
The invokeRatingService activity shows the failover feature. The partner link of this invoke has two possible implementations, which are configured in the deployment descriptor file as follows:
<properties id="RatingService"> <property name="wsdlLocation"> http://localhost:8080/axis/services/RatingService1?wsdl </property> <property name="location"> http://localhost:1234/axis/services/RatingService1 http://localhost:8080/axis/services/RatingService2 </property> </properties>
The preceding code sample shows that two endpoint locations are configured for the RatingService partner link. The first endpoint is a bad URL and the second endpoint is a good URL. Because a remote exception like this is retryable, and there is a second endpoint, Oracle BPEL Server tries to call the second endpoint, at which point, the call succeeds.
The invokeFlakyService activity, expanded in , shows system retry.
Figure 8-3 Retry with FlakyService
The partner link of this invoke is configured as follows:
<properties id="FlakyService"> <property name="wsdlLocation"> http://localhost:8080/axis/services/FlakyService?wsdl</property> <property name="location"> http://localhost:2222/axis/services/FlakyService</property> <property name="retryMaxCount">2</property> <property name="retryInterval">60</property> </properties>
If the service is not listening on port
2222, then the invoke fails with a
ConnectionRefused run-time fault. Because this is a retryable fault, and the
retryMaxCount (set to
retryInterval parameters (set to
0) are defined, Oracle BPEL Server retries twice, with
60 second intervals between each attempt. The second retry is successful.