Fault Handling
Fault Handling
1)fault-policies.xml
2)fault-bindings.xml
Fault policies file is used to define the type of faults and the action to be taken for
the particular fault.
Fault binding file is used for binding the fault policy file with the project.
Fault-policies.xml:
<faultPolicies xmlns="http://schemas.oracle.com/bpel/faultpolicy"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.oracle.com/bpel/faultpolicy"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Conditions>
<faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
name="bpelx:remoteFault">
<condition>
<action ref="ora-human"/>
</condition>
</faultName>
<faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
name="bpelx:bindingFault">
<condition>
<action ref="ora-human"/>
</condition>
</faultName>
</Conditions>
<Actions>
<Action id="ora-human">
<humanIntervention/>
</Action>
</Actions>
</faultPolicy>
</faultPolicies>
A fault binding file can have more than one fault policy tag. Here id attribute in the
faultpolicy tag defines the name of the faultpolicy.
A fault policy can have many fault name, conditions and action defined to it.
Actions is the part where all the actions to be taken are defined. This actions can be
referred inside condtion.
_____________________________________________________________________________________
FAULT-BINDINGS.XML
<faultPolicyBindings version="2.0.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.oracle.com/bpel/faultpolicy">
<composite faultPolicy="QSystemCommonFaults"/>
</faultPolicyBindings>
If you are using more than one fault policy you have to declare more than one
composite element and define the faultpolicy attribute value to the id of the fault
policy.
_____________________________________________________________________________________
You can use this files in two ways , Creating this files inside your project directory
(the location where composite.xml resides), or placing it in MDS location on the
server.
If you create the files in local, it will be useful for your project only.
If you create and place the files in MDS location it can be used globally.
However you have to mention the location of fault-policies and fault-bindings files in
your composite.xml in both the scenario.
IF LOCAL:
<property name="oracle.composite.faultPolicyFile">fault-
policies.xml</property>
<property name="oracle.composite.faultBindingFile">fault-
bindings.xml</property>
IF IN MDS:
<property name="oracle.composite.faultPolicyFile">location/fault-
policies.xml</property>
<property name="oracle.composite.faultBindingFile">location/fault-
bindings.xml</property>
Eg:
NOTE: While creating the files you must have to name it as fault-policies.xml and
fault-bindings.xml
Use this code in composite just before the bpel /mediator component tag.
_____________________________________________________________________________________
OraBPEL Technote #7
The new feature is documented in the release note of Oracle BPEL 10.1.3.3, in the chapter "Fault Management
Framework".
Another nice article on BPEL fault handling with an example is written here.
Existing exception handling in the BPEL processes will be implemented as defined in the standards for that
application.
A distinction will be made in fault policies for synchronous and a-synchronous policies.
The default fault policy, valid for all BPEL processes, will be implemented as if there was no fault policy.
Fault Policies
DefaultFaultPolicy
The default policy will catch all faults message and pass it back to the process that raises the fault. This is defined as
follows:
DefaultPolicy.xml
=============
<?xml version="1.0" encoding="UTF-8"?>
<faultPolicy
version="2.0.1"
id="DefaultPolicy"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.oracle.com/bpel/faultpolicy"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!--
This section describes default conditions.
Build more conditions with faultName, test and action
-->
<!--
CONDITIONS
-->
<Conditions>
<faultName>
<condition>
<action ref="ora-rethrow-fault"/>
</condition>
</faultName>
</Conditions>
<!--
ACTIONS
-->
<Actions>
<!--
This is an action will bubble up the fault
-->
<Action id="ora-rethrow-fault">
<rethrowFault/>
</Action>
</Actions>
</faultPolicy>
$ORACLE_HOME/domain/<domain-name>/config/fault-policies
For example
$ORACLE_HOME/domain/default/config/fault-policies
The bind the DefaultPolicy.xml file as default fault policy handler. The following file must be created and filled with the
following content:
$ORACLE_HOME/domain/<domain-name>/config/fault-bindings.xml
For example
$ORACLE_HOME/domain/default/config/fault-bindings.xml
===================================================
<?xml version="1.0" encoding="UTF-8"?>
<faultPolicyBindings
version="2.0.1"
xmlns="http://schemas.oracle.com/bpel/faultpolicy"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!--
DefaultPolicy is defined
in ./fault-policies/DefaultPolicy.xml
-->
<process faultPolicy="DefaultPolicy"/>
<partnerLink faultPolicy="DefaultPolicy"/>
</faultPolicyBindings>
Fault Policy Synchronous:
The fault policy for synchronous process is as follows. When a binding or remote fault occurs, it will retry calling this
invoke/partnerlink again. It will retry this 5 times with an interval of 4 seconds. This means that if after 20 seconds the
retry was still failing, it executes a re-thrown. Meaning that the fault is passed back to the process. The process will
now handle the fault in his normal exception handling.
FaultPolicySynchronous.xml
==========================
<?xml version="1.0" encoding="UTF-8"?>
<faultPolicy
version="2.0.1"
id="FaultPolicySynchronous"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.oracle.com/bpel/faultpolicy"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!--
This section describes fault conditions.
Build more conditions with faultName, test and action
-->
<!--
CONDITIONS
-->
<Conditions>
<!--
Fault if wsdlRuntimeLocation is not reachable
-->
<faultName
xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
name="bpelx:remoteFault">
<condition>
<action ref="ora-retry"/>
</condition>
</faultName>
<!--
Fault if location port is not reachable
-->
<faultName
xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
name="bpelx:bindingFault">
<condition>
<action ref="ora-retry"/>
</condition>
</faultName>
</Conditions>
<!--
ACTIONS
-->
<Actions>
<!--
This action will attempt 5 retries with intervals of 4 seconds
retry after 4, 8, 12, 16, 20 seconds
-->
<Action id="ora-retry">
<retry>
<retryCount>5</retryCount>
<retryInterval>4</retryInterval>
<retryFailureAction ref="ora-rethrow-fault"/>
</retry>
</Action>
<!--
This is an action will cause a replay scope fault
-->
<Action id="ora-replay-scope">
<replayScope/>
</Action>
<!--
This is an action will bubble up the fault
-->
<Action id="ora-rethrow-fault">
<rethrowFault/>
</Action>
<!--
This is an action will mark the work item
to be "pending recovery from console"
-->
<Action id="ora-human-intervention">
<humanIntervention/>
</Action>
<!--
This action will cause the instance to terminate
-->
<Action id="ora-terminate">
<abort/>
</Action>
</Actions>
</faultPolicy>
FaultPolicyASynchronous
The fault policy for a-synchronous process is as follows. When a binding or remote fault occurs, it will retry calling this
invoke/partner link again. It will retry this 10 times with an interval of 2 seconds, growing exceptional. This means that
9 attempts with increased intervals of 2 seconds, it retries after 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 seconds, this
will result in a duration of 2046 seconds; approx 34 minutes.
If after 34 minutes the retry was still failing, it executes a human-intervention. Meaning that the fault is waiting for
human input. In the Oracle BPEL Console, on the activation tab, the processes is waiting on an action of the
administrator.
FaultPolicyASynchronous.xml
==========================
<?xml version="1.0" encoding="UTF-8"?>
<faultPolicy
version="2.0.1"
id="FaultPolicyASynchronous"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.oracle.com/bpel/faultpolicy"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!--
This section describes fault conditions.
Build more conditions with faultName, test and action
-->
<!--
CONDITIONS
-->
<Conditions>
<!--
Fault if wsdlRuntimeLocation is not reachable
-->
<faultName
xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
name="bpelx:remoteFault">
<condition>
<action ref="ora-retry"/>
</condition>
</faultName>
<!--
Fault if location port is not reachable
-->
<faultName
xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
name="bpelx:bindingFault">
<condition>
<action ref="ora-retry"/>
</condition>
</faultName>
</Conditions>
<!--
ACTIONS
-->
<Actions>
<!--
This action will attempt 9 retries with increased intervals of 2 seconds
retry after 2, 4, 8, 16, 32, 64, 128, 256, 512 seconds,
this will result in a duration of 1022 seconds; approx 17 minutes
-->
<Action id="ora-retry">
<retry>
<retryCount>9</retryCount>
<retryInterval>2</retryInterval>
<exponentialBackoff/>
<retryFailureAction ref="ora-human-intervention"/>
</retry>
</Action>
<!--
This is an action will cause a replay scope fault
-->
<Action id="ora-replay-scope">
<replayScope/>
</Action>
<!--
This is an action will bubble up the fault
-->
<Action id="ora-rethrow-fault">
<rethrowFault/>
</Action>
<!--
This is an action will mark the work item to be "pending recovery from console"
-->
<Action id="ora-human-intervention">
<humanIntervention/>
</Action>
<!--
This action will cause the instance to terminate
-->
<Action id="ora-terminate">
<abort/>
</Action>
</Actions>
</faultPolicy>
Implementation
The fault policies are read during startup of the Oracle BPEL PM. This means that new fault policies or policies that
are changed can only be made available by restarting the BPEL PM.
All processes should be aware of the new fault policy mechanism. This means that synchronous process should use
the "FaultPolicySynchronous" policy. A-Synchronous process should use the "FaultPolicyASynchronous" policy.
To implement the fault policy in a BPEL process, add the following lines in the BPEL.XML file for each process, just
before the "</BPELProcess>" tag:
Synchronous processes:
<faultPolicyBindings>
<process faultPolicy="FaultPolicySynchronous"/>
</faultPolicyBindings>
A-Synchronous processes:
<faultPolicyBindings>
<process faultPolicy="FaultPolicyASynchronous"/>
</faultPolicyBindings>
18 comments:
I have used the Fault Policies in a similar way as you have suggested on BPEL projects implemented by my
organisation. However when placing the fault policy details, as suggested in your post, in the bpel.xml file of
the process. However JDeveloper seems to remove the settings when you edit the process (e.g.Add Partner
Links). Have you experienced these problems? Is your Best Practice to only add these settings once the
process has been completed?
Thanks David
This a known issue :-). If you change the content of the bpel.xml file, make sure you do not have any other
windows open; meaning close all BPEL diagrams. JDeveloper is caching the bpel.xml file, closing the .bpel
files will release the memoery, and use the file you have changed.
Marc
Thats Great :) Thanks for the response and the tip Marc
David
Alex said...
Hi Marc,
I'm trying to have a general policy that that just retry's a couple of times and then goes for the Human
Interaction.
This is done. My problem currently is that i have an external Audit System that i need to update when the
process goes into the Human Interaction. Is there any way that i can call a webservice when a remote fault
occurs using the Fault Policies?
rohit said...
Alex,
The retry and java-action are chaining actions, i.e. you may call another action after executing them.
For your case, you may do retry -> java-action -> human-interaction.
Hi there,
I am software developer in eds best shore. Currently i am using oracle soa suite to build up the prototype of
concept for our client. During my work, i have so many issues regarding the soa suite, especially in bpel and
esb.
So what i care about is that could you provide a msn address or other im contacts to me, which is better for
us to discuss about some related problems. I am really need your help~ thanks a lot. BTW, my msn address
is [email protected] Look forward to hear from you soon
Mahesh said...
Hi I am working on conceptualizing a Fault handling framework so that i can be used in any environment.
Here are the Key Requirements
A generic fault handling framework based on the Error Hospital pattern capable of handling any fault as
they occur by taking appropriate actions.
A generic framework for logging and monitoring accessible to all systems participating in an integration
process.
Fulfil the requirements inflicted by the Integration Platform with respect to security, scalability and
robustness.
Two frameworks working independent of each other.
Many different user groups can potentially be involved is both the monitoring and the fault handling
processes.
End Users Persons who use the business applications
Support level 1 In house resources providing end user support related to business faults
Support level 2 In house resources providing end user support related to technical support
Operations Technical resources typically providing support on infrastructure, hardware, operating
systems and middleware components.
Can u help me in designing these. If you have already worked on this, would you be able to assist.
Thanks,
Mahesh
scott said...
Marc,
I have applied the two policies as you wrote them. Two of my bpel processes were constructed as "empty".
The instance is created after a read from an AQ adapter. (it is the start of the bpel) After the message is
loaded from the AQ adapter, the bpel uses a partner link to talk to a web service. I undeployed the web
service and observed the exponential back off of the retries (not to mention the fact that I could see the
policies getting loaded in the logs). When the retries gave up, I was expecting the human interaction, but
that was not available. What could I be missing?
Thanks,
SCott
scott said...
I am now fairly certain that only the default policy is getting executed. From review of the log, I can see the
other two policies loading, and I have opened the suitcase "jar" and verified that the bpel.xml has the
required element added.
OK - just discovered that my version of the default policy is different than yours. It is still the original default
policy. What is the consequence of that?
senthil said...
Hi Marc,
I am trying to implement fault policy at process level(bpel.xml) for a BPEL process that is initiated by a
synchronous JMS Adapter. This BPEL process inturn calls a synchronous child BPEL process. But when I
switch off the child process and try to initiate the first BPEL with JMS Adapter, no instances appear on the
BPEL Console. In the logs I am getting the following exception,
But if I remove the fault policy binding from bpel.xml I am able to see faulted instances of the first bpel in the
console.
hii,
I am studying about these bpel fualt policies, i am implementing one demo on this concept.
can anybody tell the actions which we are specifying in the fault policies like BPELJavaAction can anybody
tell tell exactlt where we have to write the Java function and where we have to placa the .Calss file of that
function, in order to cretae a link betwwen the java action which we have mentioned in the Fault policy to the
Java Function which we have created.
Did you read the release notes in this article. An example is described there.
Anonymous said...
Hello Everyone,
Gomzi! said...
Thanks for the information. Your blog sure has great material for all users!!
shookie10 said...
I have a situation where I created a new domain in the BPEL console and the domain shows the directories
for the fault policies (eg fault-polocies dir) on the server. Now I create another domain and the fault-polocies
directory is not there. Has anyone else seen this. How do you correct it. I don't remember doing anything
specific when I created the first domain to create the directories/files.
Thanks
BradW said...
All I can say is thanks for the great example. We have a starting point we can work with. Having done fault
handling inside my BPEL process before, this keeps it much simpler and consistent!
Thanks!
BradW
Srinivas said...
Heidaar, How to invoke another bpel process( to send notification) or How to send the notification(email)
from fault policy action part?
S said...
We have defined the Fault policies for Sync and Async process exactly as mentioned as above. It is working
fine most of time, but few times when the process takes more time and the end system (OSB) throws
TIME_OUT_ERROR, in the BPEL process the fault is getting handled, it has been put for Human
Intervention but it is getting faulted and since there is no handler for that, the BPEL state is changing to
Faulted and closed. Any idea?
So when we are using this framework, it takes precedence over catch and catchAll
blocks in BPEL.
A fault policy bindings file associates the policies defined in a fault policy file with
the SOA composite application or the component.
A fault policy file defines fault conditions and their corresponding fault recovery actions.
Each fault condition specifies a particular fault or group of faults, which it attempts to
handle, and the corresponding action for it.
And these files should be created based on below XML schema.
http://download.oracle.com/docs/cd/E12839_01/integration.1111/e10224/med_faul
thandling.htm#BABJGAEI
We can have these xml files in the same directory as the composite.xml file of the SOA
composite application or we can place it in a different location and access those by using
below properties in composite.xml
oracle.composite.faultPolicyFile
oracle.composite.faultBindingFile
Ex:
<property
name="oracle.composite.faultPolicyFile">oramds:/apps/components/faultpolicies/fa
ult-Policies.xml
</property>
<property
name="oracle.composite.faultBindingFile">oramds://apps/components/faultpolicyfil
es/fault-bindings.xml
</property>
Below diagram shows how BPEL process behaves when we use fault-policy frame-
work.
So when we are using this framework, it takes precedence over catch and catchAll
blocks in BPEL.
fault-policies.xml :
fault-bindings.xml:
<faultPolicyBindings version="2.0.1"
xmlns="http://schemas.oracle.com/bpel/faultpolicy"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<name>TestProcess</name>
</component>
<name>SecondProcess</name>
</component>
</faultPolicyBindings>
Infault-policies.xml condition section, we can have actions based on the evaluation of fault-
variable available on the fault. Like below.
<condition>
<test>$fault.code="ABC Error"</test>
<action ref="ora-terminate"/>
</condition>
retry
human-intervention
replay
rethrow
terminate
javaAction
We will see how to use custom java code in fault-policy framework in coming posts.
Regards
Best practices for service interface design in SOA, Part 1:
Exploring the development, interfaces, and operation
semantics of services
Mikhail Genkin ([email protected]), Certified IT Architect, IBM, Software Group
Tags for this article: best, design, for, in, interface, practices, service, soa
Tag this!
Introduction
In the context of implementing SOA solutions, the structure of a service interface is very
important. A poorly structured service interface can greatly complicate development of many
service consumer applications that use that interface. From a business point of view, poorly
structured service interfaces can complicate development and optimization of business processes.
Conversely, well-designed service interfaces can accelerate development schedules and facilitate
business-level flexibility.
Web services are a natural fit for constructing SOA solutions. Many existing and future industry
standards in the Web services arena, such as SOAP, Java API for XML-based RPC (JAX-RPC),
WSDL, and WS-* specifications) ensure interoperability. Standards-based tools included in
popular development environments, such as IBM Rational Application Developer and IBM
WebSphere Integration Developer, reduce development times and accelerate SOA projects.
Service granularity
Operation signature
Development approaches
Programming models and development tools based on XML and Web services define three
approaches to building Web services:
Bottom up
Top down
Following this approach, the developer first defines the Web service interface
using WSDL and XML Schema (XSD) constructs, then generates skeletal
implementation code for the service. Next the developer completes the
skeleton service implementation. Most leading IDEs, such as Rational
Application Developer V6 and WebSphere Integration Developer V6, provide
tooling support for this approach.
This approach involves a combination of the previous two. The developer first
defines the service interface using WSDL and XSD, and generates a skeletal
implementation for the service. If necessary, the developer may also use a
bottom-up technique to expose existing code using a convenient application
programming interface (API). Then the developer writes code that converts
between the newly designed interface and the old interface.
Many skilled Java developers like to use bottom-up techniques to accelerate Web services
development in SOA projects. They develop implementations for new services in Java first, then
use the powerful code generation wizards to create WSDL interfaces for these services. Although
this approach can speed the implementation of individual services, it frequently means problems
for the SOA project as a whole.
Problems occur because bottom-up generation frequently results in type definitions that cannot
be reused and multiple types defined to represent semantically equivalent information.
Best practice: Use the top down and meet in the middle
development approach, rather than bottom-up techniques. Design
your service interface using XSD and WSDL, then generate skeletal
Java code.
The bottom up development approach is appropriate when there is an existing body of legacy
code (for example JavaBeans, EJB, COBOL, and so on). With this approach, you should
carefully review interfaces of existing classes before generating the WSDL interface. If the Java
interface contains any of the following, it can be considered weakly typed:
You should consider either refactoring your legacy code to ensure that interfaces are strongly
typed or building a mediation that will wrapper the weakly typed interface with a strongly typed
one.
The XML Schema specification defines a broader range of constructs for describing message
structures than Java. Some of these include choices, derivation by restriction, annotation, and
others. Therefore, it is better to define your interface using WSDL and XSD, and generate
skeletal Java code rather than doing it the other way around.
Together WSDL and XSD represent the technology-neutral interface definition language that can
be used for SOA implementations. The WSDL/XSD interface definition can be used to generate
skeletal implementations in many languages in addition to Java (for example COBOL and C++).
Back to top
Interface granularity
A service interface should generally contain more than one operation. Operations defined as part
of a single service interface should be semantically related. A large number of services, each
containing a single operation or small number of operations, indicates inappropriate service
granularity. Conversely, a very small number of services (or a single service) containing a large
number of operations likewise indicates inappropriate service granularity.
Let's use an example to better understand how decisions about service interface granularity
should be made. One of the most commonly encountered scenarios in SOA projects involves
exposing existing transactions as Web services. In this example, an existing S390 mainframe
hosts a CICS region that runs many COBOL transactions used to manage customer information,
product pricing, and product availability.
Each COBOL transaction can be exposed as a single Web service operation. We could define a
service called MyS390Service, for example, with a single interface that defines operations for all
COBOL transactions running on that mainframe. This produces an interface with dozens of
operations that client applications can use to invoke any transaction on that system, regardless of
whether the transaction is related to customer management or product pricing.
This approach makes the service harder to understand and, as a result, hard to reuse in business
processes -- ultimately resulting in many versions of the service. (More about service versioning
in subsequent articles.) We encourage developers to not group operations based solely on the
physical system that they are targeting.
Another approach involves defining a new interface for every transaction on the system. This
results in many interfaces and eventually, many services that use these interfaces. Service
proliferation, in turn, results in service governance problems, making it harder to pursue effective
code reuse.
The best approach is to define interfaces (WSDL port types) in a way that groups semantically
related transactions. In our example, COBOL transactions that operate on customer information
are semantically related in that they operate on the same set of data.
If customer information resides on multiple enterprise information systems (EIS), rather than on
one mainframe as in the previous example, you should first define physical system-specific
interfaces grouping customer information-related transactions, and then aggregate these
interfaces into a single interface for customer information management. Figure 1 shows the
interface aggregation approach.
In Figure 1 you see an example of aggregating system-specific interfaces into a generic interface.
EIS1 provides access to customer information, such as addresses. EIS2 contains customer
account data. The generic CustomerInfo interface combines operations from the two EIS-specific
interfaces.
Figure 1. Aggregating system-specific interfaces into a generic one
Back to top
Operation signature
Use of faults
Best practice guidelines in this section can help you design services that can be readily reused
and incorporated into business processes.
As soon as a client application invokes a one-way operation using, for example, a JAX-RPC-
compliant Java proxy, it returns control immediately to the calling client application thread.
There is no way for the client application to know whether or not the message was successfully
delivered or even dispatched.
This may, or may not, be acceptable to the calling application. If it is acceptable, then the
application can invoke one-way operations and rely on the message-oriented middleware, such
as SIBus or WebSphere MQ, to ensure message delivery to its intended destination. If this is not
acceptable, then the application can use a synchronous invocation technique to implement
asynchronous semantics (described in a moment).
A request-response operation can define a request message, a response message, and any number
of fault messages. When a client uses a synchronous protocol (such as HTTP) to send a request
message (for example, a JAX-RPC-compliant Java proxy), the proxy blocks the calling thread
until it receives either a response or a fault from the service.
Faults convey error information about failures that occur during the service invocation. In many
processing scenarios, this information is just as important as the data returned during a "happy-
path" invocation.
Services are frequently invoked by end-user-facing applications that need to convey error
information to the end user. Many business processes need to immediately examine error
information returned by a service invoked with a synchronous binding, allowing them to direct
subsequent processing appropriately. In these cases you should always strive to design your
interfaces using request-response operations that use faults. (Faults and error handling are
covered in more detail in a subsequent article in this series.) Use a synchronous protocol with a
request-response interaction pattern, and define faults that are understandable by the end user.
Best practice: Define faults in your service interfaces and use them
in your service implementations.
One-way invocations
The service requestor does not expect or need a response. The application or
the business process simply drops the message off to be delivered to the
intended destination and continues processing.
Asynchronous request with delayed response
String transNumber;
Try
{
transNumber = debitAccount(amount);
}
catch (SystemFault sysFault)
{
System.out.println(sysFault.getError());
// React to system level fault
}
catch(BusinessFault busFault)
{
System.out.println(sysFault.getError());
// React to business level fault
}
The calling application uses the transaction number to poll the service provider interface for the
business response message at a later time (asynchronous behavior). You could also return a
Boolean to simply indicate success, when the calling application is not interested in the response
and to convey that the request message is successfully delivered.
For example, a service interface could define operations called setCustomerNumber() and
getCustomerInfo(). In a stateful exchange the service requestor calls the
setCustomerNumber() operation first, passing in the customer number. The service provider
retains the customer number in memory. Next the service requestor calls the
getCustomerInfo() operation. The service provider then returns a customer information
response that corresponds to the customer number set in the previous invocation.
In a stateless exchange, the service provider defines the getCustomerInfo() operation so that it
takes the customer number as an input parameter. The service provider does not need to define
the setCustomerNumber() operation nor does the service requestor need to invoke it. Each
operation invocation represents a separate transaction, with the request message containing all of
the necessary information to complete it.
Stateless interfaces are considered superior in the context of building an SOA. A stateless
interface can be readily reused by many service consumer applications that are free to manage
state in the manner best suited to each application.
The request messages contain data that will be used by the service to perform the business logic
of the operation. These messages can also contain data that are more pertinent to system-level
processing associated with the transaction, rather than business logic performed by the
transaction. Examples of these data include:
Similarly, the response message issued by the service operation can contain system-level data,
such as:
These system-level data have to be processed either by the service provider application, in
addition to the business-level data, or by the enterprise service bus (ESB) infrastructure. In the
context of building SOA solutions, it is much better to structure your service interface so that
system-relevant data can be processed separately from the business-relevant data.
The SOAP specification stipulates that the SOAP message can contain the SOAP header, the
body, and any number of user-defined headers. You should define and use custom headers to
carry system-relevant information that is specific to your business or project. Avoid putting
system-relevant information into the body of your message. This allows the ESB infrastructure to
process the information without parsing the message body (performance intensive).
Back to top
Summary
SOA allows enterprises to evolve their IT infrastructure in a flexible way. Web services provide
an ideal technology for implementing an SOA. Well-designed service interfaces can facilitate an
SOA implementation, while poorly designed ones can greatly complicate it. In this article you
explored best practices for the high-level design of your service interfaces.
Stay tuned for subsequent articles, which describe best practices for structuring your WSDL
service definitions, techniques for error handling, partitioning information between message
body and headers, and batch processing.
Resources
Learn
Read more about the IBM vision of SOA and IT infrastructure solutions.
"Web services programming tips and tricks: Using SOAP headers with JAX-
RPC" (developerWorks, Oct 2003) explains how to use headers in your Web
services.
Download IBM product evaluation versions and get your hands on additional
application development tools and middleware products from DB2, Lotus,
Rational, Tivoli, and WebSphere.
Discuss
Participate in the discussion forum.
Mikhail Genkin is a Certified IT Architect working with IBM Integrated Software and Services
for WebSphere. He works with key IBM customers, helping them implement business
integration solutions and service-oriented architectures using the latest IBM products. He has
also contributed to several releases of VisualAge for Java, Enterprise Edition; WebSphere
Application Server, Enterprise Edition; and WebSphere Application Developer, Integration
Edition; WebSphere Business Integration Server Foundation; and WebSphere Process Server.
Mikhail has authored many industry publications focusing on Web services, Java Connector
Architecture and process choreography, and is a frequent presenter at industry conferences.
Close [x]
Report abuse
Thank you. This entry has been flagged for moderator attention.
Close [x]
Report abuse
Report abuse submission failed. Please try again later.
Close [x]
developerWorks: Sign in
IBM ID:
Password:
The first time you sign into developerWorks, a profile is created for you. This profile includes the
first name, last name, and display name you identified when you registered with
developerWorks. Select information in your developerWorks profile is displayed to the
public, but you may edit the information at any time. Your first name, last name (unless you
choose to hide them), and display name will accompany the content that you post.
Close [x]
The first time you sign in to developerWorks, a profile is created for you, so you need to choose
a display name. Your display name accompanies the content you post on developerWorks.
Please choose a display name between 3-31 characters. Your display name must be unique in
the developerWorks community and should not be your email address for privacy reasons.
1 star 1 star
2 stars 2 stars
3 stars 3 stars
4 stars 4 stars
5 stars 5 stars
Submit
Comments
Add comment:
Best practice: Use the top down and meet in the middle development approach, rather than
bottom-up techniques. Design your service interface using XSD and WSDL, then generate
skeletal Java code.
Hi I am little bit disagree with you. Most important thing is to Interface definition and their
message type.
Either you first generate Interface in Implementing language (i.e. Java) or XSD it little matters,
ultimately both are same thing only difference is that in one is in java and other definition is xml.
You have just wasted your time to write this article and also wasting time of reader.
Dear publisher,
Please do not public value less article is your site. Few and valuable article is much better than to
many less valuable articles. IBM SOMA is itself sufficient to address many things. Try to publish
and enhance such type of valuable things.
Report abuse
Best practice: Use the top down and meet in the middle development approach, rather than
bottom-up techniques. Design your service interface using XSD and WSDL, then generate
skeletal Java code.
Hi I am little bit disagree with you. Most important thing is to Interface definition and their
message type.
Either you first generate Interface in Implementing language (i.e. Java) or XSD it little matters,
ultimately both are same thing only difference is that in one is in java and other definition is xml.
You have just wasted your time to write this article and also wasting time of reader.
Dear publisher,
Please do not public value less article is your site. Few and valuable article is much better than to
many less valuable articles. IBM SOMA is itself sufficient to address many things. Try to publish
and enhance such type of valuable things.
Report abuse
I would love a point of view on how to describe an operation. For instance, when updating an
email address in a customer record, should use make an operation called "email change" or
provide a generic "update customer" operation. What are the architectural decisions you should
make?
Report abuse
Rooman, I have been musing over this same topic (OSB vs BPM) here
http://www.javamonamour.org/2010/11/osb-vs-soa-suite.html
Report abuse
I found this article very interesting and useful. Especially the best practise notes. I have a
question - when should we go for ESB and when to go for BPM?
day, February 24, 2011
In Oracle SOA 11g, faults can be categorized broadly into two categories:- System Faults and Custom Faults.So, let
us get started to see how it works.In this first example, we are going to see how faults are propagated.
First,open JDev and create a new SOA Application and a SOA project, select empty composite template.Now drag
and drop a BPEL process onto your composite application.Name it FaultHandlerBPEL and choose synchronous
template;leave the default input and output and make sure the "Expose as SOAP service" check box is checked.
Hit ok once you are done.In the FaultHandlerBPEL process, we are going to handle the faults.Drag another BPEL
process.Name it FaultThrowerBPEL.Like before, choose synchronous template and accept the default input and
output.However, do not expose this BPEL process .i.e. the check box "Expose as SOAP service" should be
unchecked.
As the name implies, the FaultThrowerBPEL process throws a fault Now wire the FaultHandlerBPEL to the
FaultThrowerBPEL process.Your composite should look like the following image:-
Now, double click on the FaultThrowerBPEL process to open the BPEL process editor.Now,drag a Throw activity
between the receive and reply activity.Name the activity ThrowFault.
Now double click on the Throw activity.A window will pop up.Click on the magnifying glass as shown in the image
below to select the fault.
In the fault chooser window, expand the System Faults node and select remoteFault.Hit ok once you are done.
This will bring you back to the previous window.Now click on the green plus sign to add a fault variable as shown in
the image below:-
Accept the default name and scope in the variable creation window.Hit Ok twice to come back to the BPEL process.
So in the previous steps, what we have done is we have created a throw activity which throws a remoteFault.While
throwing the fault, we have also specified a fault variable.Using the throw activity, we can throw system faults and
custom faults.However, the custom faults are discussed later.So, if you are familiar with java, up to now we have
written something like this:-
Notice that, once we create a fault variable, a new WSDL file is added to our project.The name of the WSDL file is
RuntimeFault.wsdl.The wsdl file is a simple one which contains a message on which the fault variable is based on.It
is important to mention here that in SOA 11g, the fault variables must be WSDL message based,be that a custom
fault variable or a system fault variable.
Now, drag and drop an Assign activity just before the Throw activity.Name it AssignFaultDetails.The BPEL file should
look like the following image:-
Now double click on the assign activity.Add a copy operation.
Choose expression on the from side and enter the string '007'.On the to side,expand the FaultVar node and select the
code part.
Hit Ok once you are done.Now,add another copy operation.On the from side, select expression and enter the string
'My Fault Summary'.On the to side, expand the FaultVar node and select the summary part
.
Add another copy operation.Like before, on the from side select expression and enter the string 'My Fault Details'.On
the two side, expand the FaultVar node and select detail node.Hit Ok twice to complete the Assign activity.
So the assign activity populates the fault variable with some dummy data before the fault is thrown. This completes
our FaultThrowerBPEL process.
Next open the composite.xml and double click on the FaultHandlerBPEL to open the BPEL editor.Next, drag and drop
an Invoke activity onto the BPEL process between the Receive and Reply activity.Double click on the invoke
activity.Enter the name InvokeFaultThrower.Next click on the magnifying glass beside the Partner Link as indicated
in the following image:-
The partner link chooser dialog opens.Select the FaultThrowerBPEL.faultthrowerbpel_client partner link and hit ok.
Back in the invoke dialog, create input and output variables.Choose the default name.Your BPEL process should look
like the following image.
Add an Assign activity before the invoke activity.Name it initialize variable.Create a copy operation as shown in the
follwing image:-
Hit Ok twice to come back to the BPEL process.Add another activity after the Invoke activity and before the Reply
activity.Call it IntializeOutput.Create a new copy operation as shown in the following image:-
Hit Ok twice to come back to the BPEL process.Now click on the validate icon on the upper left corner of the BPEL
process as shown on the image below:-
All the warning signs from the BPEL process should disappear now.If you test the process now and invoke the
FaultHandlerBPEL, when executing the invoke activity InvokeFaultThrower, a fault is going to be thrown.This is
because the FaultThrowerBPEL is going to be invoked which is going to throw a remoteFault.As we do not have any
catch or catchAll activity in the FaultThrowerBPEL, the fault is going to be propagated to the FaultHandlerBPEL.
Now add a catch all branch.To do this, click on the add catch all branch icon as indicated in the image below:-
A new catch all branch is going to be added to the BPEL process.Expand the catch all activity and drag and drop an
Assign activity under the catchAll activity and name it PopulateOutput.The BPEL process should now look like the
following image:-
Double click to open the Assign activity and add a copy operation.On the from side select, expression,open the
expression builder and enter expression:-
concat(ora:getFaultName(),'::',ora:getFaultAsString())
On the to side, select the result element as shown in the image below:-
The function ora:getFaultName() returns the fault name i.e. remoteFault in this case.The function
ora:getFaultAsString() returns the details of the fault which contains all the parts i.e. code, summary and detail.Next
drag and drop a Reply activity under the catchAll branch just below the PopulateOutput Asign activity.Your BPEL
process should look like the following image:-
Double click to open the Reply activity.Enter replyOutput as the name.Now select the partner link as before.In the
partner link chooser, select the faulthandlerbpel_client partner link.Hit ok to comeback to the previous window.
Now click on the magnifying glass beside the Variable chooser as shown in the image below:-
Now deploy and test the service from the EM console.A fault is going to be returned when you invoke the
ErrorHandlerBPEL from the EM console.
Now we are going to see how we can return a fault from a synchronous BPEL process.To do this, open the
FaultThrower BPEL process. Next add a catch branch by clicking on the add catch branch as indicated in the image
below:-
Now double click on the catch branch that is created .Now we are going to choose the fault that we intend to catch
which is, in this case, a remoteFault.Click on the magnifying glass icon as indicated in the image below to bring up
the fault chooser window.
In the fault chooser window, select remoteFault.Hit Ok once you are done.
Next click on the magnifying glass icon as indicated in the image below to select a fault variable.Here, we are going
to reuse the same variable that we created while throwing the fault.Alternatively, you can create a new fault variable
by clicking on the green plus icon.In this case, the fault variable is going to be automatically populated when the fault
is caught.
.
Next, choose the FaultVar and hit Ok once you are done.Hit Ok again to complete the catch activity.So in java syntax,
we have written something like this:-
catch(RemoteFault faultVar){}
Now drag and drop a Reply activity under the catch activity.Your BPEL process is going to look like the following
image.
Next we are going to configure the reply activity to reply with a fault.Double click on the Reply activity.Enter
ReplyFault as name.Choose the faultthrowerbpel_client partner link.Now, select the fault variable as the variable.Next
click on the magnifying glass as indicated in the following image to choose the fault that we intend to return.
In the fault chooser dialog, select remoteFault.Hit Ok once you are done.
The reply activity should look like as shown in the following image.
Hit Ok to complete the reply activity.The BPEL process should look like the following image.
Next,we have to configure the operation for the FaultThrower BPEL to indicate that he process can return a fault.To
do this, open the FaultThrower.wsdl file and go to source.Notice that the RuntimeFault.wsdl is imported into this
WSDL automatically.
Now, add a new fault inside the operation.The fault should be based on the message as defined in the
RuntimeFault.wsdl.file.Make sure the namespace is declared.
This completes the BPEL process.Now deploy and test the web service.The behavior is going to be the same;this
time though, the fault is caught by the FaultThrowerBPEL.Once caught, the FaultThrowerBPEL replies to the calling
BPEL i,e, the FaultHandlerBPEL in this case with a remoteFault.This remoteFault is then caught by the catchAll
activity inside the FaultHandlerBPEL.So in java syntax, we are doing something like this in the FaultThrowerBPEL:-
....
catch(RemoteFault faultVar){
throw new RemoteFault(faultVar);
}
In my next post, I am going to show another powerful fault handling mechanism which is the fault handling
framework.Hope this helps
On the Oracle Forums someone had a question on how to construct your own fault message based on the fault-part of the wsdl
element.
In this blog we will add several activities to the flow to constantly see the output which will be generated by the proxy service.
For the business service i used the helloworld service and imported the wsdl resource and xsd.
To be able to throw the custom soap fault from within the proxy service to the service caller i edited the same wsdl, and added the
fault part to the wsdl with my own fault response.
RESOURCES
wsdl
view sourceprint?
01.<definitions targetNamespace="http://hello.service.iteye.nl/"
02. name="MyHelloServiceService" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
03. xmlns:tns="http://hello.service.iteye.nl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
04. xmlns="http://schemas.xmlsoap.org/wsdl/">
05. <types>
06. <xsd:schema>
07. <xsd:import namespace="http://hello.service.iteye.nl/"
08. schemaLocation="XMLSchema_-896882874.xsd" />
09. </xsd:schema>
10. </types>
11. <message name="hello">
12. <part name="parameters" element="tns:hello" />
13. </message>
14. <message name="helloResponse">
15. <part name="parameters" element="tns:helloResponse" />
16. </message>
17. <message name="helloFaultResponse">
18. <part name="parameters" element="tns:helloFaultResponse" />
19. </message>
20.
21. <portType name="MyHelloService">
22. <operation name="hello">
23. <input message="tns:hello" />
24. <output message="tns:helloResponse" />
25. <fault name ="helloFaultResponse" message="tns:helloFaultResponse" />
26. </operation>
27. </portType>
28. <binding name="MyHelloServicePortBinding" type="tns:MyHelloService">
29. <soap:binding transport="http://schemas.xmlsoap.org/soap/http"
30. style="document" />
31. <operation name="hello">
32. <soap:operation soapAction="" />
33. <input>
34. <soap:body use="literal" />
35. </input>
36. <output>
37. <soap:body use="literal" />
38. </output>
39. <fault name ="helloFaultResponse" >
40. <soap:body use="literal" />
41. </fault>
42. </operation>
43. </binding>
44. <service name="MyHelloServiceService">
45. <port name="MyHelloServicePort" binding="tns:MyHelloServicePortBinding">
46. <soap:address
47. location="http://localhost:7001/MyHelloService/MyHelloServiceService" />
48. </port>
49. </service>
50.</definitions>
xsd
view sourceprint?
01.<?xml version="1.0" encoding="UTF-8"?>
02.<xs:schema xmlns:tns="http://hello.service.iteye.nl/"
xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://hello.service.iteye.nl/"
version="1.0">
03. <xs:element name="hello" type="tns:hello"/>
04. <xs:element name="helloResponse" type="tns:helloResponse"/>
05. <xs:element name="helloFaultResponse" type="tns:helloFaultResponse"/>
06. <xs:complexType name="hello">
07. <xs:sequence>
08. <xs:element name="arg0" type="xs:string" minOccurs="0"/>
09. </xs:sequence>
10. </xs:complexType>
11. <xs:complexType name="helloResponse">
12. <xs:sequence>
13. <xs:element name="return" type="xs:string" minOccurs="0"/>
14. </xs:sequence>
15. </xs:complexType>
16. <xs:complexType name="helloFaultResponse">
17. <xs:sequence>
18. <xs:element name="errorCode" type="xs:string" minOccurs="0"/>
19. <xs:element name="reason" type="xs:string" minOccurs="0"/>
20. <xs:element name="location">
21. <xs:complexType>
22. <xs:sequence>
23. <xs:element name="node" type="xs:string"/>
24. <xs:element name="path" type="xs:string"/>
25. </xs:sequence>
26. </xs:complexType>
27. </xs:element>
28. <xs:element name="operation" type="xs:string"/>
29. <xs:element name="uri" type="xs:string"/>
30. <xs:element name="host" type="xs:string"/>
31. <xs:element name="request_body" type="xs:string"/>
32. </xs:sequence>
33. </xs:complexType>
34.</xs:schema>
SOAPUI
We will be using soapUI to test the soap faults, and also check the http headers we receive back on the invokes of the proxy
service.
Create a new project and add the wsdl of the deployed proxy service.
The service comes back with a helloResponse and HTTP Response of 200
ERROR SITUATION1
Change the endpoint of the business service to some non-existing endpoint. At this point we wont add any error handling yet, just to
see the response coming back from the Oracle Service Bus.
Oracle Service Bus generated a SOAP Fault and in the details part we will find extra info about in which part of the process it failed.
For faultstring it will concat the values errorCode and reason.
The service comes back with a HTTP Response of 500, Internal Server Error.
The service fails, the error gets propogated to the service error handler, in here we do nothing with it, and its get propogated to the
toplevel error handler, the system error handler.
ERROR SITUATION3 WITH SERIVCE ERROR HANDLER AND REPLY SUCCESS
Only thing we now are going to add is the reply activity in the serivce error handler. First add the Reply With Success.
Now the response in soapUI will look like this
So the business service triggers a soap fault, we end up in the service error handler, and over here we handle the soap fault and
decide our self what to reply back to the caller. In this case we replied back with success.
So we receive HTTP Response code of 200, but no payload in the body.
Lets try to send back a helloResponse back from the service error handler.
view sourceprint?
1.<tns:helloResponse xmlns:tns="http://hello.service.iteye.nl/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
2. <return>Returning helloResponse from within the service error handler</return>
3.</tns:helloResponse>
In this case we also end up in the service error handler, we construct the soap body, and add the helloResponse to it.
We still get a HTTP Response of 200 back.
This scenario we can use if you never want to reply back a soap fault to the caller. So we propogate all errors to the service error
handler, and in here we decide what were going to do with it.
In case of no soap faults, we can construct our own helloResponse. So were actually transforming a soap fault to a business fault,
reply it back on the output of the wsdl and the caller itself can decide what wants to do with it. Since the soap fault wont be thrown
back to him, he needs to check the body of the response to actually see if any error happened.
In this reply we only used some static message of Returning helloResponse from within the service error handler. At this point the
context of the $fault is lost and the caller wont know anything about the real error.
If we still want to reply back any information about the fault context we can also enrich the response with values from the $fault.
for example :
view sourceprint?
1.<soap-env:Body>
2.<ns2:helloResponse xmlns:ns2="http://hello.service.iteye.nl/">
3. <return>Returning helloResponse from within the service error handler,
{concat($fault/ctx:errorCode/text(),' - ', $fault/ctx:reason/text())}</return>
4.</ns2:helloResponse>
5.</soap-env:Body>
ERROR SITUATION4 WITH SERVICE ERROR HANDLER AND REPLY FAILURE
The only situation which is left is the construction of the soap fault, and reply it back on the fault-element of the wsdl with the correct
HTTP Response.
First only add the Reply with Failure activity, to see what the response will be.
Again we end up in the service error handler, since we dont do any handling of the error itself besides a reply with failure no soap
fault will get propogated (neither the one generated by the service bus itself) either.
So we receive a normal empty soap body response, but with HTTP Response of 500, Interal Server Error.
The only thing whats left is constructing the soap fault payload.
If you check the payload of the first error testcase we see the soap envelope with soap fault needs to look like this
view sourceprint?
01.<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
02. <soapenv:Body>
03. <soapenv:Fault>
04. <faultcode>soapenv:Server</faultcode>
05. <faultstring>BEA-380002: Not Found</faultstring>
06. <detail>
07. <b>in here we will add our own soap fault response payload message</b>
08. </detail>
09. </soapenv:Fault>
10. </soapenv:Body>
11.</soapenv:Envelope>
The format of the replacement we will base on the helloFaultResponse of our xsd and when we reply it back we apply to the
interface of the wsdl, specifically to the fault-part of the invoke of hello-operation.
To show you a bit what is possible in constructing, the helloFaultResponse is rather full of elements. Its just to show you whats
possible with constructing the payload and how you can enrich it by making use of the $fault, $inbound, $outbound, etc.
view sourceprint?
01.<soap-env:Body>
02. <soap-env:Fault>
03. <faultcode
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">soapenv:Server</faultcode>
04. <faultstring>{concat($fault/ctx:errorCode,': ',$fault/ctx:reason)}</faultstring>
05. <detail>
06. <ns2:helloFaultResponse xmlns:ns2="http://hello.service.iteye.nl/">
07. <errorCode>{$fault/ctx:errorCode/text()}</errorCode>
08. <reason>{$fault/ctx:reason/text()}</reason>
09. <location>
10. <node>{$fault/ctx:location/ctx:node/text()}</node>
11. <path>{$fault/ctx:location/ctx:path/text()}</path>
12. </location>
13. <operation>{$inbound/ctx:service/ctx:operation/text()}</operation>
14. <uri>{$inbound/ctx:transport/ctx:uri/text()}</uri>
15. <host>{$inbound/ctx:transport/ctx:request/tp:headers/http:Host/text()}</host>
16. <request_body>{$copyBody}</request_body>
17. </ns2:helloFaultResponse>
18. </detail>
19. </soap-env:Fault>
20.</soap-env:Body>
I hope its a bit clear on how to handle the faults in the Oracle Service Bus. In my testcases i only added the logic to the service error
handler. But we can also the the error handlers to the other locations like stages and routing activities. It depends on the logic you
want to execute at which place you want to handle the error itself.
In this article, we are going to learn about exception handling options available within SOA Suite 11g.
Exceptions can be divided into two categories: Business Faults, and Runtime Faults. Usually we let the
Business Faults be handled at component level and Runtime Faults at framework level. BPEL and
Mediator handle exceptions differently. Lets examine various scenarios:
Synchronous Requests
When exceptions arise in synchronous requests, we will not get enough time to perform any corrective
measures as response needs to be returned to the requestor immediately. In such cases, we can only
return faults to the requestor. This is true for both BPEL and Mediator.
BPEL can catch, throw and compensate for exceptions. Mediator can catch multiple exceptions per
operation and perform transformations before returning faults to the initial caller.
Asynchronous Requests
As the client of the service is not expecting an immediate response, asynchronous requests provide us
with enough time to correct any issues arising in the request flow.
Error Hospital, an exception management tool provided by SOA Suite, lets us handle such exceptions
through standard, out-of-the-box facilities. All requests with exceptions, if not handled explicitly, are
sent to Error Hospital. Once enqueued, these requests can be examined and corrected through
Enterprise Management console.
SOA Suite 11g offers an excellent tool to handle exceptions at framework level. Usually business faults
are handled at component level and system faults at framework level.
Fault Management Framework lets us handle exceptions through simple XML directives. Fault policies
can be defined in a file called fault-policies.xml. We can declaratively specify exceptions to be handled
through human intervention, retried, terminated or a combination of any of these actions.
These policies can be bound to the components of a composite at various granular levels. Please refer
to Oracle documentation for more details.
Please see the Fault Management Tutorial to learn how to use validations and handle exceptions in a
composite.
In the present lesson, lets see how Error Hospital can come to rescue. We will first run Human Workflow Example
with incorrect values and see how transaction fails. Then, we will make slight change to the Mediator to see how
the failed transaction can be retried.
Lets create an entry in Orders.txt file with an item that doesnt exist in ITEMS table. In my case, ITEMS table
contains two items with IDs 1 and 2.
Redeploy the composite and copy same Order.txt file to the poller directory.
Go the EM Dashboard and see deployed process instance. We can that it is in
Recovery Needed state.
We can see the process instance is in Recovery Needed state instead of
Faulted. Click on Recover link at the bottom of the page as shown
above.
Fault Trace shows the details of recoverable error. Click on error message to
see error details. Below error message, we can see editable payload with an
option to either Retry or Abort the transaction.
Change Item ID to 1 and Retry the transaction.
Next lesson, to be published very soon, will show usage of Fault Management
Framework through simple example. Stay tuned
Fault Handling in Oracle SOA Suite : Advanced Concepts
Filed under: BPEL, BPM, Fault Handling, Fault Management, Oracle SOA Suite, SOA, Weblogic Tags: BPEL, BPM, Fault Bindings,
Fault Handling and Management in Oracle SOA Suite 11g, Fault Management through Java, Fault Policies, Mediator, Retrying Faults
in SOA Suite Arun Pareek @ 6:04 am
This tutorial is meant to cover extensively the mechanism that we can adopt for Fault
Management for a SOA Suite composite. It will deal with a fairly overall strategy for handling
faults and dealing with them in various ways.
Before diving more into advanced concepts of Handling Faults let me present a small
introduction covering the basics of a Service composite.
1. Service components BPEL Processes, Business Rule, Human Task, Mediator. These are used to construct a SOA
composite application. A service engine corresponding to the service component is also available.
2. Binding components Establish connection between a SOA composite and external world.
3. Services provide an entry point to SOA composite application.
4. Binding defines the protocols that communicate with the service like SOAP/HTTP, JCA adapter etc.
5. WSDL advertises capabilities of the service.
6. References enables a SOA composite application to send messages to external services
7. Wires enable connection between service components.
Coming to Fault Handling in a composite there are primarily two types of faults
1. Business faults Occurs when application executes THROW activity or an invoke receives fault as response.
Fault name is specified by the BPEL process service component. This fault is caught by the fault handler using
Fault name and fault variable.
2. Runtime faults Thrown by system. Most of these faults are provided out of the box. These faults are associated
with RunTimeFaultMessage and are included in http://schemas.oracle.com/bpel/extension namespace.
Oracle SOA Suite gives us an option of configuring fault and fault actions using policies. This
means that we can create policies in response to a specific type of exception. Policies are defined
in a file that by default is called fault-policies.xml
1. The fault condition that activates the policy blockwe specify what type of fault(s) the policy is relevant for. We
can then apply even more finer grained policy and actions based on error codes, error messages etc.
2. The action(s) that should be performed when the condition is satisfied. An action for an fault may be to retry it
for a certain number of time at a specified interval, or to mark it in recovery for human intervention, use a custom
Java code or simply to throw the fault back. If the fault is rethrown then if we have specified any explicit catch
block in our BPEL process that will be executed.
It should also be noted that fault policies need to be explicitly associated with composites,
components, or references. This is done in a fault-bindings.xml file. Fault bindings link the
composite, specific components in the composite, or specific references in the components on
the one hand to one of the fault policies on the other.
Have a look at the diagram below to understand a mechanism to throw a fault from a service
composite, identify the fault type and then take necessary action.
The following post will try and cover all aspects of what is covered in the diagram above.
Consider the following fault-policies.xml. Read the comments in the XML to understand what
each of the condition, action and property is about.
view source
print?
01 <faultPolicies xmlns="http://schemas.oracle.com/bpel/faultpolicy">
03 <Conditions>
<faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
05
name="bpelx:remoteFault">
06 <condition>
07 <test>$fault.code/code="WSDLReadingError"</test>
08 <action ref="ora-rethrow-fault"/>
09 </condition>
10 <condition>
11 <action ref="ora-retry"/>
12 </condition>
13 </faultName>
<faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
14
name="bpelx:bindingFault">
15 <condition>
16 <action ref="java-fault-handler"/>
17 </condition>
18 </faultName>
<faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
19
name="bpelx:runtimeFault">
20 <condition>
21 <action ref="java-fault-handler"/>
22 </condition>
23 </faultName>
24 </Conditions>
25 <Actions>
<!-- This Action will invoke a Custom Java Class to process Faults. Also
26 depending upon the returnValueanother action will be invoked whic is
specified by the ref attribute. This demosntrates chaining of Actions"-->
27 <Action id="java-fault-handler">
28 <javaAction className="com.beatech.faultapp.CustomFaultHandler"
defaultAction="ora-human-intervention" propertySet="properties">
30 </javaAction>
31 </Action>
<!-- This Action will mark the instance as "Pending for Recovery" in the EM
32
console -->
33 <Action id="ora-human-intervention">
34 <humanIntervention/>
35 </Action>
37 <Action id="ora-rethrow-fault">
38 <rethrowFault/>
39 </Action>
40 <!--This action will attempt 3 retries with intervals of 120 seconds -->
41 <Action id="ora-retry">
42 <retry>
43 <retryCount>3</retryCount>
44 <retryInterval>120</retryInterval>
45 <retryFailureAction ref="java-fault-handler"/>
46 </retry>
47 </Action>
49 <Action id="ora-terminate">
50 <abort/>
51 </Action>
52 </Actions>
<!--Properties can be used to pass values to the Java class as a Map that
53
can be used by the Class -->
54 <Properties>
55 <propertySet name="properties">
56 <property name="myProperty1">propertyValue1</property>
57 <property name="myProperty2">propertyValue2</property>
58 <property name="myPropertyN">propertyValueN</property>
59 </propertySet>
60 </Properties>
61 </faultPolicy>
62 </faultPolicies>
Inside the custom Java fault handler we can also use a switch that acts on the returnValue to
chain another Action.
view source
print?
6 </javaaction>
The next step will be to create a fault-bindings.xml file to simply bound the fault policy file to
the composite.
view source
print?
<faultPolicyBindings version="2.0.1"
1
xmlns="http://schemas.oracle.com/bpel/faultpolicy">
2 <composite faultPolicy="CompositeFaultPolicy"/>
3 </faultPolicyBindings>
Finally we have to add two properties in the composite.xml to let the composite know about
them
<property name=oracle.composite.faultPolicyFile>fault-
policies.xml></property>
<property name=oracle.composite.faultBindingFile>fault-
bindings.xml></property>
We can use different names and locations for the fault policies and fault bindings files, by setting
the properties oracle.composite.faultPolicyFile and oracle.composite.faultBindingFile in the
composite.xml to configure these custom files.
For example we can refer to these files even from the MDS.
<property name=oracle.composite.faultPolicyFile>oramds://apps/policy/fault-
policies.xml></property>
<property name=oracle.composite.faultBindingFile>oramds://apps/policy/fault-
bindings.xml></property>
Once we hit a fault in our composite that has a custom Java Action the java class
CustomFaultHandler will be instantiated. Here is one example of a Java Class.
The custom Java class has to implement the interface IFaultRecoveryJavaClass that defines two
methods i.e handleRetrySuccess and handleFault. The custom Java class
CustomFaultHandler has access to the IFaultRecoveryContext containing information about
the composite, the fault, and the policy.
view source
print?
01 package com.beatech.faultapp;
02 import com.collaxa.cube.engine.fp.BPELFaultRecoveryContextImpl;</pre>
03 import com.oracle.bpel.client.config.faultpolicy.IBPELFaultRecoveryContext;
04 import java.util.Map;
05 import oracle.integration.platform.faultpolicy.IFaultRecoveryContext;
06 import oracle.integration.platform.faultpolicy.IFaultRecoveryJavaClass;
07
09 public CustomFaultHandler() {
10 super();
11 }
12
14 System.out.println("Retry Success");
15 handleFault(iFaultRecoveryContext);
16 }
17
System.out.println("****************Fault Metadata*************************
20
*******");
System.out.println("*******************************************************
25
*******");
30 {
32 }
System.out.println("****************Fault Details**************************
34
******");
36 {
System.out.println("*******************************************************
42
****");
43 }
45 return "Manual";
46 }
47 }
1. Log the fault/part of fault in a flat file, database or error queue in a specified enterprise format.
2. We can even configure to send an Email to the support group for remedy and action. (Use custom Java Email
code or use the UMS java/ejb APIs to do so)
3. Return a flag with an appropriate post Action. This flag determines what action needs to be taken next
The java class would require the SOA and BPEL runtime in classpath to compile and execute.
To make sure that when the composite instances faults out and the fault-policy.xml is able to
instantiate this class we have to make it available in the servers classpath.
There are a couple of ways to do that. Here is one of the way to achieve it.
1. Compile your Java Project and export it as a jar file (say CustomFaultHandling.jar)
2. Go to <Middleware Home>\Oracle_SOA1\soa\modules\oracle.soa.bpel_11.1.1 directory of your Oracle SOA
Suite installation.
3. Copy the CustomFaultHandling.jar in the above directory
4. Unjar the oracle.soa.bpel.jar and edit the MANIFEST.MF to add an entry of the above jar in the classpath.
1. Pack the jar again and restart both the Managed and Admin Server.
2. Another way is to drop the CustomFaultHandling.jar in the <Middleware
Home>\Oracle_SOA1\soa\modules\oracle.soa.ext_11.1.1 and run Ant on the build.xml file present in the
directory.
Interestingly we also have an option in the EM console to retry all faults for a composite by
setting some values in custom MBeans. They are available as Advanced BPEL properties in the
SOA Infra engine.
The MBean that allows recovery of faulted instances is RecoveryConfig. It has two options for
retrying
1. RecurringScheduleConfig : A recovery window may be specified (most probably off peak hours) to recover all
faulted instances. Messages being recovered can be throttled by limiting the number of messages picked up on
each run by specifying the maxMessageRaiseSize.
2. StartupScheduleConfig : With this setting on all faulted instances are automatically retried when the soa server
is booted up for restart.
http://download.oracle.com/docs/cd/E14571_01/relnotes.1111/e10133/soa.htm#RNLIN1052
There is a small lacuna though here. It is not always possible to recover automatically. Auto-
recovery is subject to some conditions.
1. Scenario A: The BPEL code uses a fault-policy and a fault is handled using the ora-human-intervention
activity, then the fault is marked as Recoverable and the instance state is set to Running.
2. Scenario B: The BPEL code uses a fault-policy and a fault is caught and re-thrown using the ora-rethrow-
fault action, then the fault is marked as Recoverable and the instance state is set to Faulted; provided the
fault is a recoverable one (like URL was not available).
All is not lost however. The instances can still be recovered from the console though. However
for most practical purposes it isnt desirable that a huge number of composite instances that are
marked for recovery for a remote fault (say end point not available) are retried automatically. It
is natural that we will yearn to automate this part as well.
Here is a sample code that gets all remote faults that are marked as recoverable from the Custom
Java Class and retries them.
view source
print?
01 package com.beatech.salapp;
02
03 import java.util.Hashtable;
04 import java.util.List;
05
06 import javax.naming.Context;
07
08 import oracle.soa.management.facade.Fault;
09 import oracle.soa.management.facade.FaultRecoveryActionTypeConstants;
10 import oracle.soa.management.facade.Locator;
11 import oracle.soa.management.facade.LocatorFactory;
12 import oracle.soa.management.facade.bpel.BPELServiceEngine;
13 import oracle.soa.management.util.FaultFilter;
14
16
17 private Locator locator = null;
19
20 public FaultRecovery() {
21 locator = this.getLocator();
22 try {
23 mBPELServiceEngine =
24 (BPELServiceEngine)locator.getServiceEngine(Locator.SE_BPEL);
25 } catch (Exception e) {
26 e.printStackTrace();
27 }
28 }
29
32 jndiProps.put(Context.PROVIDER_URL,"t3://localhost:4003/soa-infra");
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialConte
33
xtFactory");
34 jndiProps.put(Context.SECURITY_PRINCIPAL, "weblogic");
35 jndiProps.put(Context.SECURITY_CREDENTIALS, "welcome123");
36 jndiProps.put("dedicated.connection", "true");
37 return jndiProps;
38 }
39
41
42 try {
43 return LocatorFactory.createLocator(getJndiProps());
44 } catch (Exception e) {
45 e.printStackTrace();
46 }
47 return null;
48 }
49
51 try {
53 /* Set Search Filters like composite Name, Instance Ids, fault Names etc.
56 */
filter.setFaultName("{http://schemas.oracle.com/bpel/extension}remoteFault"
58
);
59 filter.setRecoverable(true);
60
6 System.out.println("=========================Recoverable Faults============
3 ======================================");
6 System.out.println("=======================================================
5 ======================================");
75 }
7 //mBPELServiceEngine.recoverFaults(faultList.toArray(new Fault[faultList.si
7 ze()]), FaultRecoveryActionTypeConstants.ACTION_RETRY);
7
8
79 } catch (Exception e) {
80 e.printStackTrace();
81 }
82
83 }
84
87 faultRecovery.recoverFaults();
88 }
89 }
Replace the values in the property map with the ones in your server. Remember to give the
managed server port in the Provider URL. Run the Java Class and you would see that the
recoverable faults are printed.
Verify the same from the console
Run the Java program again but this time uncomment the line below
view source
print?
//mBPELServiceEngine.recoverFaults(faultList.toArray(new
1
Fault[faultList.size()]), FaultRecoveryActionTypeConstants.ACTION_RETRY);
This will result in all faults marked with <strong>Recovery</strong> icon to be retried. So if the
remote endpoint is responding and active now the processes will complete.
There are a host of other things that we can do in this Java Class.
The following code snippet if inserted in the code will replace any process variable with a new
value before retrying. (May be used in case of Binding or Business Faults)
view source
print?
0
for (Fault fault : faultList)
4
05 {
11 {
13 }
//Get Input Variable Data from the Activity, Modify it with a new value and
14
recover
21 mBPELServiceEngine.setVariable(fault,"activityRequestMessage",value);
22
mBPELServiceEngine.recoverFault(fault,FaultRecoveryActionTypeConstants.ACTI
24
ON_RETRY,null);
25 }
The following JARS would be required in the classpath for the above Java Code
<MWHOME>\oracle_common\modules\oracle.fabriccommon_11.1.1\fabric-
common.jar
<MWHOME>\jdeveloper\soa\modules\oracle.soa.mgmt_11.1.1\soa-infra-
mgmt.jar
<MWHOME>\wlserver_10.3\server\lib\weblogic.jar
<MWHOME>\jdeveloper\soa\modules\oracle.soa.fabric_11.1.1\oracle-soa-
client-api.jar
<MWHOME>\oracle_common\webservices\wsclient_extended.jar
The post discussed the different approaches and strategies for handling faults in a composite in
SOA Suite. Let me conclude this article by describing a few best practices around Fault
Handling.
1. Create fault (catch block) for each partner link. For each partner link, have a catch block for all possible errors.
Idea is not to let errors go to catchAll block.
2. CatchAll should be kept for all errors that cannot be thought of during design time.
3. Classify errors into various types runtime, remote, binding, validation, Business errors etc.
4. Notification should be setup in production, so that, errors are sent to concerned teams by E-Mail. Console
need not be visited for finding out status of execution.
5. Use Catch Block for non-partner link error.
6. Every retry defined in fault policy causes a commit of the transaction. Dehydration will be reached and
threads released.
7. Automated recovery can be created by creating a fault table, persisting the queue and having an agent to re-
submit the job (For example writing a Timer agent to invoke the Java code we wrote to recover instances) . Can be
achieved through scripts. Use only PUBLISHED API of ESB or QUEUE (AQ etc.) for re-submission. Another
example would be to use WLST to change the RecoveryConfig MBean to configure recovery window to retry all
faulted instances.
8. Handle Rollback fault by providing No Action in fault policy.
9. Remember Receive, OnMessage, On Alarm, Wait, CheckPoint (Activity for forcing Java thread to store its current
state to Dehydration store) will cause storing of current state to dehydration store and threads will be released.
10. Always use MDS to store fault policies and bindings to increase their reuse for multiple composites and
projects