You are on page 1of 88

Fault handling in SOA 11g

Handling faults using Fault management framework :

To handle faults out of bpel processes we need two important files.

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:

<?xml version="1.0" encoding="UTF-8"?>

<faultPolicies xmlns="http://schemas.oracle.com/bpel/faultpolicy"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<faultPolicy version="0.0.1" id="QSystemCommonFaults"

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.

_____________________________________________________________________________________

NOTE: ALL FILES ARE CASE SENSITIVE

FAULT-BINDINGS.XML

<?xml version="1.0" encoding="UTF-8"?>

<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.

_____________________________________________________________________________________

WAYS TO USE THIS FILES:

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.
_____________________________________________________________________________________

AN EXAMPLE FOR USING FAULT MANAGEMENT:

1) Create a project which invokes other service.

2) Create Fault-policies.xml and fault-bindings.xml with the code mentioned


above in this document.
3) Add reference to this files in composite.xml(use the local property tag code
mentioned above)

4) Deploy the project.


5) Now undeploy the service you are invoking from this project.
6) Test this project.
7) This will show timeout exception and recovery options will be created.

8) You can recover this by selecting the instace number->recovery


BPEL Fault Policies; best practice
Introduction
Apart of the fault handling within the BPEL processes itself, a new feature is available in BPEL. This is called the fault
handling. Previous the fault must all be handled within each process. An article on this is written in:

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".

BPEL 10.1.3.3 Release notes

Another nice article on BPEL fault handling with an example is written here.

Fault Business Rules


The fault policy is implemented for all the BPEL processes based on the following rules:

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 policies will be implemented at Oracle BPEL Process level.

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>

The DefaultPolicy.xml file should be created in the following directory

$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>

Copy the FaultPolicySynchronous.xml into the $ORACLE_HOME/bpel/domains/<domain-name>/config/fault-policies


directory.

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>

Copy the FaultPolicyASynchronous.xml into the $ORACLE_HOME/bpel/domains/<domain-name>/config/fault-


policies directory.

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>

Posted by Marc Kelderman SOA Blog at 3/10/2008 11:47:00 AM

Email ThisBlogThis!Share to TwitterShare to Facebook

18 comments:

David Gaskell said...

Thanks for the Post Marc.

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

11 March, 2008 10:48

Marc Kelderman SOA Blog said...

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

11 March, 2008 11:17

David Gaskell said...

Thats Great :) Thanks for the response and the tip Marc

David

11 March, 2008 12:35

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?

08 May, 2008 17:14

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.

And call the external websevice in you java action implementation.

12 June, 2008 00:56


Anonymous said...

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 yuechao1982@hotmailc.com Look forward to hear from you soon

26 June, 2008 04:30

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.

i can be contacted on mahesh.boovanahalli@gmail.com

Thanks,
Mahesh

15 August, 2008 10:54

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

25 September, 2008 00:58

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?

25 September, 2008 03:29

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,

Error while invoking bean "activity manager": [com.collaxa.cube.engine.core.InstanceNotFoundException:


Instance not found in datasource.
The process domain was unable to fetch the instance with key "6920002" from the datasource.
Please check that the instance key "6920002" refers to a valid instance that has been started and not
removed from the process domain.
]
ORABPEL-02152

Instance not found in datasource.


The process domain was unable to fetch the instance with key "6920002" from the datasource.
Please check that the instance key "6920002" refers to a valid instance that has been started and not
removed from the process domain.

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.

17 November, 2008 18:47


Anonymous said...

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.

Hoping for help

18 November, 2008 06:41

Marc Kelderman SOA Blog said...

Did you read the release notes in this article. An example is described there.

18 November, 2008 08:15

Anonymous said...

Hello Everyone,

Can anybody tell me How to use JMS adapter in bpel.


I am getting problem in where to define those JMS_queues and topics how they will appear in our JMS
adapter.

27 November, 2008 08:34

Gomzi! said...

Thanks for the information. Your blog sure has great material for all users!!

keep up the good work.!

14 July, 2009 06:57

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

18 August, 2009 23:06

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

04 February, 2010 00:31

Srinivas said...

Heidaar, How to invoke another bpel process( to send notification) or How to send the notification(email)
from fault policy action part?

24 November, 2010 22:14

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.

Fault-policy frame work in SOA 11g


In this post we will discuss the fault-policy framework in SOA 11g.
Conceptual wise no changes in this release when compare to 10g. But some changes are
there in placing these files and etc.
First of all this framework will work only for the faults at invoke activity.
To implement fault-policy framework we have to have two xml files called fault-
bindings.xml and fault-policies.xml.

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.

Below are the sample fault-policies and fault-bindings.xml

fault-policies.xml :

<?xml version="1.0" encoding="UTF-8"?>


<faultPolicies xmlns="http://schemas.oracle.com/bpel/faultpolicy"
xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<faultPolicy version="2.0.1" id="PannPolicy1">
<Conditions>
<faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
name="bpelx:remoteFault">
<condition>
<action ref="ora-terminate"/>
</condition>
</faultName>
<faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension"
name="bpelx:bindingFault">
<condition>
<action ref="ora-retry"/>
</condition>
<condition>
<action ref="ora-human-intervention"/>
</condition>
</faultName>
</Conditions>
<Actions>
<Action id="ora-terminate">
<abort/>
</Action>
<Action id="ora-retry">
<retry>
<retryCount>2</retryCount>
<retryInterval>2</retryInterval>
<exponentialBackoff/>
</retry>
</Action>
<Action id="ora-human-intervention">
<humanIntervention/>
</Action>
</Actions>
</faultPolicy>
</faultPolicies>

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"

<composite faultPolicy=" PannPolicy 1"/>

<component faultPolicy=" PannPolicy 1 ">

<name>TestProcess</name>

</component>

<component faultPolicy=" PannPolicy 1 ">

<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>

Some predefind actions were provided by oracle are:

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 (genkin@ca.ibm.com), Certified IT Architect, IBM, Software Group

Summary: Service-Oriented Architecture (SOA) emphasizes loose coupling between different


systems within an enterprise. Service interface structure is of primary importance in SOA
because poorly designed service interfaces can have a negative effect on all applications that
need to use them. Well-designed service interfaces can accelerate project schedules and make
your SOA solution more responsive to business needs. This article is the first in a series that
focuses on best practices for service interface design, including high-level aspects of
development approaches, service granularity, and operation signatures. Subsequent articles in
this series examine best practices for structuring Web Services Description Language (WSDL)
documents and fault handling.

View more content in this series

Tags for this article: best, design, for, in, interface, practices, service, soa

Tag this!

Update My dW interests (Log in | What's this?) Skip to help for Update My dW


interests

Date: 20 Mar 2007


Level: Intermediate

Comments: 5 (View | Add comment - Sign in)

Average rating (35 votes)

Rate this article

Introduction

Service-Oriented Architecture (SOA) is rapidly becoming the dominant architectural style in


many enterprises. The primary purpose of building an SOA solution is to empower the enterprise
to be more responsive to business needs by loosely coupling its systems. One of the main goals
of the design of your Web services within an SOA solution is to enable rapid construction of
business processes. You also want to facilitate application integration both within the enterprise
and with external business partners.

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.

This article focuses on high-level aspects of service interface design:

Design and development approaches

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

Leading integrated development environments (IDEs) provide tools for


creating Web service implementations from existing code (for example,
Java or COBOL). With this approach, the developer usually selects an
existing JavaBeans or an EJB component and invokes a wizard that generates
a WSDL file that can be used to invoke the bean or EJB as a Web service.

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.

Meet in the middle

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:

java.lang.Object used as either parameter or return type for a method

Collection classes (for example, java.util.Vector) used as either parameter or


return type for a method (JAX-RPC constraint)

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.

Java compared with WSDL


You can use either Java or WSDL to describe your service interface. Web services-related
specifications such as SOAP, JAX-RPC, and JAX-B define mappings that describe how types
defined in Java can be mapped into WSDL/XSD and vice versa.

Best practice: Describe your service interfaces using WSDL and


XSD instead of Java. Your service interface definition is a WSDL
port type.

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.

Best practice: A service interface (WSDL port type) should


generally contain more than one operation. Operations defined as
part of a single service interface should be semantically related by
data on which they operate.

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.

Best practice: If related information resides on multiple EISs, you


should first define physical system-specific interfaces grouping
information type-related transactions, and then aggregate these
interfaces into a single interface.

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

This section discuss the following operation signature semantics:

Synchronous compared with asynchronous interfaces

Stateful compared with stateless design

Use of faults

Header compared with payload

Best practice guidelines in this section can help you design services that can be readily reused
and incorporated into business processes.

Synchronous compared with asynchronous interfaces


A WSDL port type can contain one or more operations. Operations can be one-way or request-
response. A one-way operation can define a request message but no response message. It is not
possible to define faults messages for a one-way operation. (See Resources for more information
on WSDL.)

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.

Asynchronous interactions come in two different flavors:

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

The service requestor dispatches the request message and subsequently


polls the service for the response, or a callback is dispatched to the
requestor.

Best practice: When designing a new service, do not mix


synchronous and asynchronous invocation semantics in a single
interface (WSDL port type). If it is advantageous to support both
semantics, define separate interfaces for synchronous and
asynchronous invocations.

Listing 1 shows an example of using synchronous operations to implement asynchronous


invocation semantics. The transaction debitAccount does not have to return a value. By adding
a return value to the operation you are allowing for fault handling in client applications.

Listing 1. Using synchronous operations to implement asynchronous


invocation semantics

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
}

Sometimes a combination of synchronous and asynchronous is used to achieve desired behavior,


although this becomes complicated from a service interface standpoint. Unfortunately WSDL
doesn't provide a good way to model asynchronous behavior.
In the example above, the calling application dispatches the request message using a request-
response operation that returns a transaction number as the response message. The calling thread
blocks until it receives a confirmation that the message has been successfully delivered to its
intended destination. If problems are encountered, then both system-level and business-level
faults can be raised by either the service provider or the Web services invocation engine, and
caught by the calling application (synchronous behavior).

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.

Stateful compared with stateless interfaces

Exchanges between services can be stateful or stateless in nature. A stateful, or conversational,


exchange between services occurs when the service provider retains knowledge of data that has
been exchanged between the service consumer and the service provider during preceding
operation invocations.

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.

Best practice: Design your service interfaces for stateless


interactions. The request message passed in to the operation
should contain all information necessary to complete that
operation, regardless of the sequence in which other interface
operations are invoked.
Header compared with payload

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:

Identification of the service requestor application

Service implementation version

Dispatch and receipt timestamps

Similarly, the response message issued by the service operation can contain system-level data,
such as:

Identification of the responding application (service provider)

Receipt and dispatch timestamps

Computed response time

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).

Best practice: 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.

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.

"Service-Oriented Architecture expands the vision of Web services, Part 1"


(developerWorks, Apr 2004) has more information about implementing SOA
with Web services.

"Tip: Implement implicit and explicit SOAP headers" (developerWorks, Feb


2005) explains the difference between explicit and implicit headers, and how
the differences might impact you when developing with JAX-RPC.

"Web services programming tips and tricks: Using SOAP headers with JAX-
RPC" (developerWorks, Oct 2003) explains how to use headers in your Web
services.

Learn about wsdl:header and wsdl:headerfault elements from the Web


Services Description Language (WSDL) 1.1 Specification.

Web Services Description Language (WSDL) 1.1 provides information about


WS-Addressing and WS-Security.

Get products and technologies

Download an IBM trial version of Rational Application Developer.

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.

Check out developerWorks blogs and get involved in the developerWorks


community.

About the author

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 help

Report abuse
Thank you. This entry has been flagged for moderator attention.

Close [x]

Report abuse help

Report abuse
Report abuse submission failed. Please try again later.

Close [x]
developerWorks: Sign in

If you don't have an IBM ID and password, register here.

IBM ID:

Forgot your IBM ID?

Password:

Forgot your password?


Change your password

After sign in:


Stay on the current page

By clicking Submit, you agree to the developerWorks terms of use.

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.

All information submitted is secure.

Close [x]

Choose your display name

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.

Display name: (Must be between 3 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

Rate this article

Average rating (35 votes)

1 star 1 star

2 stars 2 stars

3 stars 3 stars

4 stars 4 stars

5 stars 5 stars

Submit
Comments

Add comment:

Sign in or register to leave a comment.

Note: HTML elements are not supported within comments.

Notify me when a comment is added1000 characters left

Total comments (5)

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.

Posted by gautambuddh on 07 July 2011

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.

Posted by gautambuddh on 07 July 2011

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?

Posted by NCCB_Albert_Wong on 08 December 2010

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

regarding Oracle products, but I guess it applies to any vendor.

Posted by PierluigiVernetto on 04 December 2010

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

Basic Fault Handling in SOA 11g


In this post, I am going to illustrate the basics of fault handling in Oracle SOA 11g.For the sake of illustration, I am
going to create a a sample application.So , let's get started.

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:-

throw new Exception();

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:-

In the variable chooser, choose the output variable.


Hit Ok twice to complete the Reply activity.In the previous steps, we created a catch all branch synonymous to java
"catch(Exception e){}".Now,inside the catch all, we have implemented an Assign activity which update the output
variable with the details of the fault and a Reply activity which replies to the calling process.

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.

Returning a fault from a synchronous BPEL process:-

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

Oracle Service Bus 11g, handling SOAP Faults


Posted on Saturday, 17 July 2010 by Eric Elzinga
15 COMMENTS BOOKMARK

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.

The flow we will be creating should be looking like this

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 HAPPY FLOW

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.

ERROR SITUATION2 WITH EMPTY SERVICE ERROR HANDLER

Now we only added an empty service error handler to the process.

The response in soapUI will still look the same.


If we we test the proxy service from the testconsole we will get the next output.

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.

Add the next replace


replace . in variable body with expression, Replace Node contents

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.

The replace i used in the service error handler

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>

And the output in soapUI

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.

Fault Management Framework

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.

1. Fault Management in BPEL

2. Fault Management in Mediator

Please see the Fault Management Tutorial to learn how to use validations and handle exceptions in a
composite.

One of the powerful features in Oracle SOA Suite is out-of-the-box Error


Hospital. In order to use this feature, Mediator component should have
parallel routing rules. Each parallel routing starts a new transaction and can
be independently controlled through EM console.

Please refer to Human Workflow Example to understand this lesson better.

MyBay synchronizes its items with MyDels datastore at frequent intervals.


MyDel expects items from all received Orders to be present in its datastore
before further processing. However, due to synchronization issues,
sometimes MyBay order items are not found in MyDels datastore. In such
cases, instead of discarding the entire batch of orders, MyDel needs to
selectively retry failed orders after rectifying the issues.

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.

Lets create an order entry in Order.txt with ItemId 3.

When Order.txt is placed in file poller directory, as expected, transaction


fails.

Click on Instance ID to go to process Flow Trace. We can see the transaction


has failed because of Foreign Constraint violation.
We cant retry this transaction. Lets slightly modify Order Router mediator to
change this behaviour.

Open OrderRouter from composite.xml and go to Routing Rules section.


Observe the both routing rules we defined earlier are sequential type.
Change them to parallel. Click OK for any information dialogs you get in
the process.

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.

Go back to the Process Dashboard and click on Instance ID again to go to


Flow Trace. We can see the transaction is successfully completed.
Though it solves bulk of our requirements, we may still want to refine fault
handling by fault category. We also may want to extend fault handling to
BPEL processes. In such cases, we can make use of Fault Management
Framework.

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.

Basic Architecture of a Service Composite in Oracle SOA Suite

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

Policies for fault handling consist of two main elements:

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">

<faultPolicy version="2.0.1" id="CompositeFaultPolicy"


xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
02
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.oracle.com/bpel/faultpolicy">

03 <Conditions>

04 <!-- Conditions can be fine grained to include Actions based on Error


Codes. If a remotefault occurs check whether it is a WSDLReadingError. If
yes then rethrow it else retry it."-->

<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">

29 <returnValue value="Manual" ref="ora-human-intervention"/>

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>

36 <!--This is an action will bubble up the fault to the Catch Blocks-->

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>

48 <!--This action will cause the instance to terminate-->

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?

<javaaction classname="com.beatech.faultapp.CustomFaultHandler" defaultaction


1
="ora-rethrow">

2 <returnValue ref="ora-rethrow" value="Rethrow"/>

3 <returnvalue ref="ora-terminate" value="Abort"/>

4 <returnvalue ref="ora-retry" value="Retry"/>

5 <returnvalue ref="ora-human-intervention" value="Manual"/>

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.

If the fault is thrown by a BPEL process we can check if its an instanceof


BPELFaultRecoveryContextImpl to get further fault details.

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

08 public class CustomFaultHandler implements IFaultRecoveryJavaClass {

09 public CustomFaultHandler() {

10 super();

11 }

12

public void handleRetrySuccess(IFaultRecoveryContext iFaultRecoveryContext)


13
{

14 System.out.println("Retry Success");

15 handleFault(iFaultRecoveryContext);

16 }

17

18 public String handleFault(IFaultRecoveryContext iFaultRecoveryContext) {

19 //Print Fault Meta Data to Console

System.out.println("****************Fault Metadata*************************
20
*******");

System.out.println("Fault policy id: " + iFaultRecoveryContext.getPolicyId(


21
));

22 System.out.println("Fault type: " + iFaultRecoveryContext.getType());

System.out.println("Partnerlink: " + iFaultRecoveryContext.getReferenceName


23
());

24 System.out.println("Port type: " + iFaultRecoveryContext.getPortType());

System.out.println("*******************************************************
25
*******");

26 //print all properties defined in the fault-policy file


27 System.out.println("Properties Set for the Fault");

28 Map props = iFaultRecoveryContext.getProperties();

29 for (Object key: props.keySet())

30 {

System.out.println("Key : " + key.toString() + " Value : " + props.get(key)


31
.toString());

32 }

33 //Print Fault Details to Console if it exists

System.out.println("****************Fault Details**************************
34
******");

35 if(iFaultRecoveryContext instanceof BPELFaultRecoveryContextImpl)

36 {

BPELFaultRecoveryContextImpl bpelCtx = (BPELFaultRecoveryContextImpl) iFaul


37
tRecoveryContext;

38 System.out.println("Fault: " + bpelCtx.getFault());

39 System.out.println("Activity: " + bpelCtx.getActivityName());

System.out.println("Composite Instance: " + bpelCtx.getCompositeInstanceId(


40
));

41 System.out.println("Composite Name: " + bpelCtx.getCompositeName());

System.out.println("*******************************************************
42
****");

43 }

44 //Custom Code to Log Fault to File/DB/JMS or send Emails etc.

45 return "Manual";

46 }

47 }

Now here is what we can do from here

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.

More details on how to use RecoverConfig Mbean can be found here

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.

Consider the scenarios below.

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).

In Scenario A, the Recoverable fault CANNOT be auto-recovered using the RecoveryConfig


MBean.
In Scenario B, the Recoverable fault can be auto-recovered on server startup and/or pre-
scheduled recovery.

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

15 public class FaultRecovery {

16
17 private Locator locator = null;

18 private BPELServiceEngine mBPELServiceEngine;

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

30 public Hashtable getJndiProps() {

31 Hashtable jndiProps = new Hashtable();

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

40 public Locator getLocator() {

41

42 try {

43 return LocatorFactory.createLocator(getJndiProps());
44 } catch (Exception e) {

45 e.printStackTrace();

46 }

47 return null;

48 }

49

50 public void recoverFaults() {

51 try {

52 System.out.println("Get All Recoverable Faults");

53 /* Set Search Filters like composite Name, Instance Ids, fault Names etc.

Here I am setting the setRevoverable filter to true to retrieve all Recover


54
able Faults.

5 Also I am setting filter on faultName as i want to programatically retry al


5 l remote Faults for resubmission.

56 */

57 FaultFilter filter = new FaultFilter();

filter.setFaultName("{http://schemas.oracle.com/bpel/extension}remoteFault"
58
);

59 filter.setRecoverable(true);

60

61 //Get faults using defined filter

62 List<Fault> faultList = mBPELServiceEngine.getFaults(filter);

6 System.out.println("=========================Recoverable Faults============
3 ======================================");

64 for (Fault fault : faultList) {

6 System.out.println("=======================================================
5 ======================================");

System.out.println("Composite DN: " + fault.getCompositeDN().getStringDN())


66
;
System.out.println("Composite Instance ID: " + fault.getCompositeInstanceId
67
());

68 System.out.println("Component Name: " + fault.getComponentName());

System.out.println("Component Instance ID: " + fault.getComponentInstanceId


69
());

70 System.out.println("Activity Name: " + fault.getLabel());

71 System.out.println("Fault ID: " + fault.getId());

72 System.out.println("Fault Name: " + fault.getName());

73 System.out.println("Recoverable flag: " + fault.isRecoverable());

74 System.out.println("Fault Message: " + fault.getMessage());

75 }

76 // Recovering all Recoverable Faults in a single call

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

85 public static void main(String[] args) {

86 FaultRecovery faultRecovery = new FaultRecovery();

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.

Using the <strong>BPELServiceEngine</strong> object we can write messages to the BPEL


audit trail, inspect the current activity, and read and update the values of BPEL variables.

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?

01 //Get faults using defined filter

02 List<Fault> faultList = mBPELServiceEngine.getFaults(filter);

0 System.out.println("=========================Recoverable Faults ===========


3 =======================================");

0
for (Fault fault : faultList)
4

05 {

0 System.out.println("=========================Read Process Variables =======


6 ==================================");

07 //Get Process Instance variables from fault object

08 String[] variables = mBPELServiceEngine.getVariableNames(fault);

09 System.out.println("Process Instance Variables:");

10 for (int i = 0; i < variables.length; i++)

11 {

12 System.out.println("Variable Name: " + variables[i]);

13 }

//Get Input Variable Data from the Activity, Modify it with a new value and
14
recover

1 System.out.println("=========================Replace Variable and Recover =


5 ===================================");

16 System.out.println("Activity Input Variable Data:");

String value =mBPELServiceEngine.getVariable(fault, "activityRequestMessage


17
");

18 System.out.println("Present value: " + value);

19 value = value.replace("remoteFault", "Modified Value");

20 System.out.println("New value: " + value);

21 mBPELServiceEngine.setVariable(fault,"activityRequestMessage",value);

22

23 // Recover Faults one by one

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.

Oracle SOA Suite Fault Handling Best Practices

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

You might also like