Oracle® BPEL Process Manager Developer's Guide 10g (10.1.3.1.0) Part Number B28981-03 |
|
|
View PDF |
Fault handling allows a BPEL process to handle error messages or other exceptions returned by outside Web services, and to generate error messages in response to business or run-time faults.
This chapter contains the following topics:
Getting Fault Details with the getFaultAsString XPath Extension Function
Using the Terminate Activity to Stop a Business Process Instance
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:SOA_Oracle_Home
\bpel\samples\tutorials\107.Exceptions
SOA_Oracle_Home
\bpel\samples\demos\ResilientDemo
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 -1000
.
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>
The 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 -1000
.
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 http://schemas.xmlsoap.org/ws/2003/03/business-process/
:
selectionFailure
conflictingReceive
conflictingRequest
mismatchedAssignmentFailure
joinFailure
forcedTermination
correlationViolation
uninitializedVariable
repeatedCompensation
invalidReply
Standard faults are defined as follows:
Typeless, meaning they do not have associated messageTypes
Not associated with any WSDL message
Caught without a fault variable:
<catch faultName="bpws:selectionFault">
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
Run-time 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 faultVariable
.
<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 messageType
RuntimeFaultMessage
. The following WSDL file defines the messageType
:
<?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>
If a faultVariable
(of messageType
RuntimeFaultMessage
) is used when catching the fault, the fault code can be queried from the faultVariable
, along with the fault summary and detail.
A 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 |
---|---|
VersionMismatch |
The processing party found an invalid namespace for the SOAP envelope element. |
MustUnderstand |
An immediate child element of the SOAP header element that was either not understood or not obeyed by the processing party contained a SOAP MustUnderstand attribute with a value of 1 . |
Client.GenericError |
Generic error on the client side |
Client.WrongNumberOfInputParts |
Input message part number mismatch |
Client.WrongNumberOfOutputParts |
Output message part number mismatch |
Client.WrongTypeOfInputPart |
Input message part type error |
Client.WrongTypeOfOutputPart |
Output message part type error |
Server.GenericError |
Generic error on the server side |
Server.NoService |
Server is up, but there is no service |
Server.NoHTTPSOAPAction |
Request is missing the HTTP SOAP action |
Server.Unauthenticated |
Request is not authenticated |
Server.Unauthorized |
Request is not authorized |
A 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.
A 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 bindingFault
and 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.
Import RuntimeFault.wsdl
into your process WSDL (located under the SOA_Oracle_Home
\bpel\system\
xmllib
directory).
Declare a variable with messageType bpelx:RuntimeFaultMessage
.
Catch it using
<catch faultName="bpelx:remoteFault" | "bpelx:bindingFault" faultName="varName">
The 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:SOA_Oracle_Home
\bpel\samples\references\Throw
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.
See Also:
Chapter 7, "Conditional Branching" for more information on setting up the conditional structure
Chapter 4, "Invoking a Synchronous Web Service" for more information on synchronous interactions
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.
See Also:
Chapter 5, "Invoking an Asynchronous Web Service" for more information on asynchronous interactions
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:SOA_Oracle_Home
\bpel\samples\references\Catch
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>
If no catch
or 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 catchAll
handler.
See Also:
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.
For example:
<compensate scope="RecordPayment"/>
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.
See Also:
"BankTransferDemo
" for a demonstration that uses a compensate activity
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:SOA_Oracle_Home
\bpel\samples\references\Terminate
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 .
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.
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 2
) and retryInterval
parameters (set to 6
0
) are defined, Oracle BPEL Server retries twice, with 60
second intervals between each attempt. The second retry is successful.