Beruflich Dokumente
Kultur Dokumente
Faults
In bpel-processes we can categorize the faults into: business faults and runtime faults. Business faults
are application specific faults and will occur when we use the “throw”-activity or if we invoke a
partnerlink which returns with some fault. It’s up to the “business” to decide what needs to be done
when the fault occurs and what activities are needed for handling it.
Besides the business faults we have the runtime faults. Runtime faults will not be defined by the user,
so we need to design parts in the process to handle them. In bpel we will make use of the catch-activity
for this. In the catch itself we can invoke our own fault-handling processes or do some other activities
(retry etc) which are needed to get a valid situation again.
Oracle made a nice technote for some good information about all the possible faults and some extra
faults defined by Oracle Process Manager.
Framework
In the good old days (before patch 10.1.3.3) we needed to design the fault-handling part for every bpel-
process.
Possibilities were there by making use of for example some Error Hospital, but still, every process
individually needed changes for being able to handle faults.
With the latest patch for the Oracle Soa Suite (10.1.3.3) , Oracle provided a new Fault Management
framework. This framework will gives us the opportunity to handle all the business and runtime faults
for an “invoke” activity. With the framework we can define 1 policy for every bpel domain.
In a so called “fault-binding” (/bpel/domains/default/config/fault-policy-binding.xml) , we can setup
which policies we’re going to use and which processes/partnerlinks/porttypes will be part of it. The
framework will use the binding in order of the following priority :
• bpel.xml
• policy defined on the server
In a so called “fault-policy” (/bpel/domains/default/config/fault-policies/DefaultPolicy.xml), we can
define what type of faults we want to catch and what actions need to get executed.
If there is already some fault-handling (catch) defined in the the bpel process, the framework will
overrule this, and use a policy if possible.
fault-policy-binding
The fault-bindings will be defined on the next location : /bpel/domains/default/config/fault-policy-
binding.xml
The xsd-schema for the fault-bindings can be found on this location : /bpel/system/xmllib/fault-policy-
binding.xsd
view source
print?
01 < ?xml version="1.0" encoding="UTF-8"?>
02 <faultpolicybindings version="2.0.1"
03 xmlns="http://schemas.oracle.com/bpel/faultpolicy"
04 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- Enabling this will cause all processes in this domain to
05
use this
06 fault policy
07 <process faultPolicy="DefaultPolicy"/>
08 -->
<!-- DefaultPolicy is defined in ./fault-
09
policies/DefaultPolicy.xml -->
10 <partnerlink faultPolicy="DefaultPolicy">
<!-- Enabling this will cause all invoke faults at partner
11
link
12 name of "creditRatingService" to use fault policy with
13 id id = DefaultPolicy
14 <name>creditRatingService
15 -->
<!-- all invoke faults at partner link below port type use
16
fault policy
17 with id = DefaultPolicy
The following entry covers the
18
samples/tutorials/122.DBAdapter/InsertWithCatch sample. -->
<porttype
19 xmlns:db="http://xmlns.oracle.com/pcbpel/adapter/db/insert/">db:insert_plt</portty
pe>
20 </partnerlink>
21 </faultpolicybindings>
In the policy we can define on several levels
(process,partnerLink,portType) if we want to make use of a policy. In
the comment of the xml you will see what needs to be turned on or off
to apply to policy.
fault-policies
The fault-policies will be defined on the next location : /bpel/domains/default/config/fault-policies. The
xsd-schema for the fault-policies can be found on this location : /bpel/system/xmllib/fault-policy.xsd.
Oracle delivers the following policy by default.
view source
print?
01 < ?xml version="1.0" encoding="UTF-8"?>
02 <faultpolicy version="2.0.1" id="DefaultPolicy"
03 xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
04 xmlns:xs="http://www.w3.org/2001/XMLSchema"
05 xmlns="http://schemas.oracle.com/bpel/faultpolicy"
06 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- This section describes fault conditions. Build more
07
conditions with faultName, test and action -->
08 <conditions>
09 <!-- Fault if wsdlRuntimeLocation is not reachable -->
<faultname xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
10
name="bpelx:remoteFault">
11 <condition>
12 <action ref="ora-retry"/>
13 </condition>
14 </faultname>
15 <!-- Fault if location port is not reachable-->
<faultname xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
16
name="bpelx:bindingFault">
17 <condition>
18 <action ref="ora-rethrow-fault"/>
19 </condition>
20 </faultname>
21 </conditions>
22 <actions>
<!-- This action will attempt 8 retries at increasing
23
intervals of 2, 4, 8, 16, 32, 64, 128, and 256 seconds. -->
24 <action id="ora-retry">
25 <retry>
26 <retrycount>8</retrycount>
27 <retryinterval>2</retryinterval>
28 <exponentialbackoff />
29 </retry>
30 </action>
31 <!-- This is an action will cause a replay scope fault-->
32 <action id="ora-replay-scope">
33 <replayscope />
34 </action>
35 <!-- This is an action will bubble up the fault-->
36 <action id="ora-rethrow-fault">
37 <rethrowfault />
38 </action>
39 <!-- This is an action will mark the work item to be "pending
recovery from console"-->
40 <action id="ora-human-intervention">
41 <humanintervention />
42 </action>
43 <!-- This action will cause the instance to terminate-->
44 <action id="ora-terminate">
45 <abort />
46 </action>
47 </actions>
48 </faultpolicy>
A policy consists of a conditions-section and an actions-section.
In the conditions-sections we will define which faults need to be
handled and which actions will be executed.
view source
print?
1 <conditions>
2 <!-- Fault if wsdlRuntimeLocation is not reachable -->
<faultname xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
3
name="bpelx:remoteFault">
4 <condition>
5 <action ref="ora-retry"/>
6 </condition>
7 </faultname>
8 </conditions>
In this part of the code the framework will “catch” all remoteFaults
and execute the ora-retry action.
view source
print?
1 <condition>
2 <test>$fault.code/code="INVALID_WSDL"</test>
3 <action ref="ora-terminate"/>
4 </condition>
In this part of the code we will check if the fault-code =
“INVALID_WSDL”. The action to be executed is : ora-terminate.
Oracle delivers a few default actions as part of the framework. At this moment that list isn’t extensible.
If we still need some custom fault-handling we could make use of the ora-java action. This action will
allow us to make us of some custom java, and inhere we will be able to decide what to do with the
fault.
Default available actions :
• ora-retry ( retry the activity )
• ora-replay-scope ( replay the scope in which the fault occurred )
• ora-rethrow-fault ( system will throw the fault to the bpel fault handlers )
• ora-human-intervention ( the current activity will freeze. In the console the user will be able to
take several actions on this
• instance )
• ora-terminate ( terminate instance )
• ora-java ( execute custom java )
Lets practice!
To show how the framework works we will build a little example. We deployed a simpe java
webservice (helloWorld). We also build a little bpel-process with a few steps in it (assign and invoke of
the java service).As part of the error-handling we added a catch on the remoteFault. In the catch we
won’t be doing any fault-handling, just the catch and an assign to the output.
To generate a remoteFault we undeployed the javaservice from the oc4j, and executed the bpel-process
again. After executing again, the process will fall into the catch we defined.
We will not change the structure of the process, and only define a new policy on the server.
First step is to define the fault-binding. fault-bindings.xml:
view source
print?
1 < ?xml version="1.0" encoding="UTF-8"?>
2 <faultpolicybindings version="2.0.1"
3 xmlns="http://schemas.oracle.com/bpel/faultpolicy"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
5 <process faultPolicy="BlogTestPolicy"/>
<!-- DefaultPolicy is defined in ./fault-
6
policies/DefaultPolicy.xml -->
7 <partnerlink faultPolicy="BlogTestPolicy"/>
8 </faultpolicybindings>
The policy is named “BlogTestPolicy” and all processes and
partnerlinks will use it.
Next step is to define the policy. BlogTestPolicy.xml:
view source
print?
01 < ?xml version="1.0" encoding="UTF-8"?>
02 <faultpolicy version="2.0.1" id="BlogTestPolicy"
03 xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
04 xmlns:xs="http://www.w3.org/2001/XMLSchema"
05 xmlns="http://schemas.oracle.com/bpel/faultpolicy"
06 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- This section describes fault conditions. Build more
07
conditions with faultName, test and action -->
08 <conditions>
09 <!-- Fault if wsdlRuntimeLocation is not reachable -->
<faultname xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
10
name="bpelx:remoteFault">
11 <condition>
12 <action ref="ora-retry"/>
13 </condition>
14 <condition>
15 <action ref="ora-human-intervention"/>
16 </condition>
17 </faultname>
18 </conditions>
19 <actions>
<!-- This action will attempt 8 retries at increasing
20
intervals of 2, 4, 8, 16, 32, 64, 128, and 256 seconds. -->
21 <action id="ora-retry">
22 <retry>
23 <retrycount>8</retrycount>
24 <retryinterval>2</retryinterval>
25 <exponentialbackoff />
26 </retry>
27 </action>
28 <!-- This is an action will cause a replay scope fault-->
29 <action id="ora-replay-scope">
30 <replayscope />
31 </action>
32 <!-- This is an action will bubble up the fault-->
33 <action id="ora-rethrow-fault">
34 <rethrowfault />
35 </action>
<!-- This is an action will mark the work item to be "pending
36
recovery from console"-->
37 <action id="ora-human-intervention">
38 <humanintervention />
39 </action>
40 <!-- This action will cause the instance to terminate-->
41 <action id="ora-terminate">
42 <abort />
43 </action>
44 </actions>
45 </faultpolicy>
We defined a policy which will handle all remoteFaults. When a
remoteFault occurs, the framework will be able to execute two
actions. First it will do the “ora-retry” action, if the fault still
occurs the next action will be executing the “ora-human-intervention”
action. After creating the policy we restart the oc4j-container to
make sure the policy will be active.
**update
To chain the actions, in this example we just added 2 actions after each other. This won’t work, and
only the last action will get executed. The way to do this is to use the retryFailureAction-element in the
action.
for example :
view source
print?
1 <action id="ora-retry">
2 <retry>
3 <retrycount>5</retrycount>
4 <retryinterval>10</retryinterval>
5 <retryfailureaction ref="ora-human-intervention"/>
6 </retry>
7 </action>
Before we start testing the framework we make sure we still use the
same situation as in the beginning. We have undeployed the
javawebservice which we will invoke in the bpel process. We left the
catch in the process. On the server we defined the policy. This
policy will now handle the remoteFault instead of the “catch” in the
bpel.
Execute the process. When we look in the console at the instance of the process we see this :
The catch in the bpel itself isn’t getting fired. When we look in the audit trail, we notice the next
message :
It looks like our policy is active. The framework applied the policy. So it first executed the ‘ora-retry’
action (no output on this) and after this it executed the ‘ora-human-intervention’ action. So at this point
we should be able to apply some other actions on the faulted activity (the invoke of the webservice).
From here we have 2 options. The first is the activities-tab. On this tab we will find all activities
executed, and which faulted with the faultname. On the left we select the ‘Pending’ state in the
‘Activity State’ checkbox. On the right we will see the faulted invoke of our webservice. If we select
the checkbox on the left of the activities we can make use of the ‘bulk update’- functionality on more
then 1 instance. We select the invoke activity and in the listbox we can select one of the following
actions :
• Retry
• Abort
• Rethrow
• Replay
• Continue
The second option is the ‘interactions’-tab available in the view when we selected the faulted instance.
In here we will find all the activities from the current process-instance. Select the invoke-activity
(sayHello). In the next screen we will see some sort of Error Hospital. Notice the new State of the
current instance : open.pending.recovery.
We will be able to update all the payload of the variables of the activities in the process, execute
different actions on them, chain the outcomes or just created new instances.
First select the variable in the “Available Variables”-listbox for which we want to update the payload.
Click the get-button. In the textarea we’re now able to insert different payload. After inserting the
correct values, click the set-button and go to the “Actions available”-listbox and select the appropriate
action. The last step is to either choice to recover the current instance, or create a new one.
In our scenario we redeployed the webservice, so the wsdl is reachable again. We updated the sayHello
inputvariable just to see some changes in the updated instance later on. After this we just click the
Recover-button. Select the visual flow, and click on the invoke activity (sayHello).
As we can see in the output. The payload of the inputVariable of the sayHello has been updated and the
framework executed the retry after it. We redeployed the webservice, so it was reachable again, and the
invoke executed correct too.
I hope with the information in this article the functionality of the new fault policy framework is a bit
clear.
Runtime Faults
* Predefined, e.g.
- remoteFault
- bindingFault
* Infrastructure faults, e.g.
- Service down
- Network outage
* Data format errors
Define conditions
* Conditions are based on faultName. e.g.
<faultName
xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
name="bpelx:remoteFault">
<condition>
<test>$fault.code/code="WSDLReadingError"</test>
<action ref="ora-terminate"/>
</condition>
<condition>
<action ref="ora-java"/>
</condition>
<test>$fault.code/code="WSDLReadingError"</test>
- one action section which references to the action defined in the same file
<action ref="ora-terminate"/>
<condition>
<action ref="ora-rethrow"/>
</condition>
Define actions
* See examples below.
<Conditions>
<!-- when bpelx:remoteFault, retry -->
<faultName
xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
name="bpelx:remoteFault">
<condition>
<action ref="ora-retry"/>
</condition>
</faultName>
* Actions
<faultPolicyBindings>
<!-- Fault on any plink/port type not specified -->
<!-- below uses policy BillingFaults -->
<process faultPolicy="BillingFaults"/>
<partnerLink xmlns:credit="http://services.otn.com" faultPolicy="CRM_
ServiceFaults">
<!-- Fault on these 2 plink will use policy CRM_ServiceFaults -->
<name>UnitedLoanService</name>
<name>StarLoanService</name>
* Domain level
- Configured in OracleAS_2\bpel\domains\default\config\fault-bindings.xml file.
<partnerLink faultPolicy="DefaultPolicy">
<!-- all invoke faults at partner link creditRatingService use DefaultPolicy
-->
<name>creditRatingService</name>
</partnerLink>
<partnerLink faultPolicy="DefaultPolicy">
<!-- all invoke faults at specific port type use DefaultPolicy -->
<portType
xmlns:db="http://xmlns.oracle.com/pcbpel/adapter/db/insert/">db:insert_plt</p
ortType>
</partnerLink>
Subprocess
Just a simple invoke of the subprocess from the mainprocess. The subprocess with throw a fault, and
this fault will be catched in the mainprocess.
It looks like the framework got active (activity yellow marked) on our custom
business fault.
Go to the activities-tab
AllBusinessFaults
The AllBusinessFaults will throw the custom business fault we ‘request’ back on the invoke in this
subprocess. Now it wil get catched by the framework and we will be able to change the values of the
subprocess instead of the mainprocess.
By using the AllBusinessFaults bpel service like a sort of composite service, we can add the custom
business faults in it and throw the one we would like to get thrown. This will work if the collection of
custom business faults isn’t that big. I’m sure there will be better solutions for this, but for the scenario
i wanted to describe inhere it was good enough for me.
Question
In the examples i provided i don’t use the fault-part of a synchronous invoke to propegate the soap-
fault back to the caller, i just throw the fault. The bpel engine itself throws the fault back to the first-
level. Whats best practice on this one ?