Oracle Service Bus 11g, handling SOAP Faults

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

<definitions targetNamespace="http://hello.service.iteye.nl/"
	name="MyHelloServiceService" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
	xmlns:tns="http://hello.service.iteye.nl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns="http://schemas.xmlsoap.org/wsdl/">
	<types>
		<xsd:schema>
			<xsd:import namespace="http://hello.service.iteye.nl/"
				schemaLocation="XMLSchema_-896882874.xsd" />
		</xsd:schema>
	</types>
	<message name="hello">
		<part name="parameters" element="tns:hello" />
	</message>
	<message name="helloResponse">
		<part name="parameters" element="tns:helloResponse" />
	</message>
	<message name="helloFaultResponse">
		<part name="parameters" element="tns:helloFaultResponse" />
	</message>
		
	<portType name="MyHelloService">
		<operation name="hello">
			<input message="tns:hello" />
			<output message="tns:helloResponse" />
			<fault name ="helloFaultResponse" message="tns:helloFaultResponse" />
		</operation>
	</portType>
	<binding name="MyHelloServicePortBinding" type="tns:MyHelloService">
		<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
			style="document" />
		<operation name="hello">
			<soap:operation soapAction="" />
			<input>
				<soap:body use="literal" />
			</input>
			<output>
				<soap:body use="literal" />
			</output>
			<fault name ="helloFaultResponse" >
			  <soap:body use="literal" />
			</fault>
		</operation>
	</binding>
	<service name="MyHelloServiceService">
		<port name="MyHelloServicePort" binding="tns:MyHelloServicePortBinding">
			<soap:address
				location="http://localhost:7001/MyHelloService/MyHelloServiceService" />
		</port>
	</service>
</definitions> 

xsd

<?xml version="1.0" encoding="UTF-8"?>
<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">
	<xs:element name="hello" type="tns:hello"/>
	<xs:element name="helloResponse" type="tns:helloResponse"/>
	<xs:element name="helloFaultResponse" type="tns:helloFaultResponse"/>
	<xs:complexType name="hello">
		<xs:sequence>
			<xs:element name="arg0" type="xs:string" minOccurs="0"/>
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="helloResponse">
		<xs:sequence>
			<xs:element name="return" type="xs:string" minOccurs="0"/>
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="helloFaultResponse">
		<xs:sequence>
			<xs:element name="errorCode" type="xs:string" minOccurs="0"/>
			<xs:element name="reason" type="xs:string" minOccurs="0"/>
			<xs:element name="location">
				<xs:complexType>
					<xs:sequence>
						<xs:element name="node" type="xs:string"/>
						<xs:element name="path" type="xs:string"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:element name="operation" type="xs:string"/>
			<xs:element name="uri" type="xs:string"/>
			<xs:element name="host" type="xs:string"/>
			<xs:element name="request_body" type="xs:string"/>			
		</xs:sequence>
	</xs:complexType>
</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 won’t 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 it’s 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.

Let’s 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

<tns:helloResponse xmlns:tns="http://hello.service.iteye.nl/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<return>Returning helloResponse from within the service error handler</return>
</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 we’re going to do with it.
In case of no soap faults, we can construct our own helloResponse. So we’re 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 won’t 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 won’t 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 :

<soap-env:Body> 
<ns2:helloResponse 	xmlns:ns2="http://hello.service.iteye.nl/">
	<return>Returning helloResponse from within the service error handler, {concat($fault/ctx:errorCode/text(),' - ', $fault/ctx:reason/text())}</return>
</ns2:helloResponse>
</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 don’t 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 what’s 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

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <soapenv:Fault>
         <faultcode>soapenv:Server</faultcode>
         <faultstring>BEA-380002: Not Found</faultstring>
         <detail>
			<b>in here we will add our own soap fault response payload message</b>
         </detail>
      </soapenv:Fault>
   </soapenv:Body>
</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. It’s just to show you what’s 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

<soap-env:Body>
	<soap-env:Fault>
		<faultcode xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">soapenv:Server</faultcode>
		<faultstring>{concat($fault/ctx:errorCode,': ',$fault/ctx:reason)}</faultstring>
		<detail>
			<ns2:helloFaultResponse xmlns:ns2="http://hello.service.iteye.nl/">
				<errorCode>{$fault/ctx:errorCode/text()}</errorCode>
				<reason>{$fault/ctx:reason/text()}</reason>
				<location>
					<node>{$fault/ctx:location/ctx:node/text()}</node>
					<path>{$fault/ctx:location/ctx:path/text()}</path>
				</location>
				<operation>{$inbound/ctx:service/ctx:operation/text()}</operation>
				<uri>{$inbound/ctx:transport/ctx:uri/text()}</uri>
				<host>{$inbound/ctx:transport/ctx:request/tp:headers/http:Host/text()}</host>
				<request_body>{$copyBody}</request_body>
			</ns2:helloFaultResponse>
		</detail>
	</soap-env:Fault>
</soap-env:Body>

And the output in soapUI

I hope it’s 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.

Share this Post:
Digg Google Bookmarks reddit Mixx StumbleUpon Technorati Yahoo! Buzz DesignFloat Delicious BlinkList Furl

44 Responses to “Oracle Service Bus 11g, handling SOAP Faults”

commenter

Thanks eric for the nice article..I do have comment, when Reply is used with Success/Failure without any assign/replace activities, i think response would contain request message(just echo) but you mentioned that it would return empty body..i am not sure if that is correct.

commenter

Will do a double check this weekend just to make sure 🙂

commenter

Chandra, it really gives me the empty soap bodys. Just did a check on both the replies and nothing else in the service error handler

commenter

Nice blog, very usefull! Maybe more detail about the mapping by OSB would be nice…

commenter

what part do you mean ?

commenter

I’ve been trying to determine how to get access to the originaly request within the fault handler. In your last example you use a variable $copyBody which contains the original request. How did you get the original request into this variable?

commenter

In the request pipeline you need to add an assign with something like

assign $body to $copyBody

this $copyBody will not get transformed during the rest of the process by osb itself. So when you arrive in the service error handler it will still have the content of the body like you started the process (so the originel request payload)

commenter

We use the $copyBody assign action in the request pipeline as well. This works fine until you add WS-Security for authentication. If the authentication fails, the request ends up in the service error handler without going into the pipeline, and your assign to copyBody action is never reached. This means the variable copyBody is empty in the service error handler, but the original body is available. You can get around this by checking if copyBody variable is empty in the service error handler. If so, use $body in your fault instead.

[…] some examples (also explained in more detail by Eric Elzinga here). A proxy service with this basic Error Handler will log the $fault and […]

commenter

hey hi…
I want to create a generic errorhandler proxy that does only errorhandling and that would be called by other proxys in their errorhandler by a service callout…i want to capture the errormessage in the calling proxys fault variable..can u guide how this can be accomplished..??

commenter

and one more thing..am able to capture the errorcode of fault in the common error handling proxy’s request pipeline ..but how to reply the response back to calling proxy and populate the error message in the fault variable of the main proxy….Kindly,help..

commenter

when you create your errorhandling proxy service of type anyXML, you could then send the content of $fault and some other metadata to the error proxy service..in here do your thing and reply back the generated soap-fault or your own defined soap fault metadata variable. In your service error handling of every proxy service which fails you could do a service callout to the error handling proxy service. As input use the $fault and the other metadata you need and wait till it comes back with the reply. In that case you should have your own custom generated $myfault variable received back from the error handling proxy service. Use this variable to do some transformation or if the variable is already defined as your soap-fault format you could replace it in the body and do the reply back with it.

commenter

Your idea is good but replacing in body and using reply back sends the message as a Response. Is there any way which we can raise an error or capture the $myfault variable into $fault?
My requirement is to capture or Customize the output from genric errorhandling proxy service and then raise an error with the same.

commenter

You don’t want to reply back a soap fault in the generic proxy service ? but instead want to manipulte the $fault, right ?

commenter

Thanks for the immediate reply..
Actually I want to manipulate in proxy service which is calling the generic proxy(error handling).
so whatever the generic proxy returns i should be able to capture it in $fault of calling proxy.

thanks in advance..

commenter

Hi Eric,
any update on this

commenter

Hi Eric,Thanks for nice blog.Can you plz post the zip file jar file of project.

commenter

I have a request with multiple orders ,if i encounter an error in any one order i want to continue processing the remaining orders ..in my response to the client i want to exclude the orders that were not processed …how do i use the fault handhler of osb

commenter

Will try to create a testcase this week when i got some spare time but i’m thinking of the next.

In the normal processing you call a service for the specific order, the response from this call you assign/append to some other variable.
in case when the order doesn’t exists you raise an error, you arrive in the stage error handler which exists in the for-each loop and you don’t do anything in it. I’m not sure if this works, but i could imagine you can continue the looping for the other orders without appending the response from the failed order.

But will need to make a testcase to be sure about this

commenter

I could jar my code and send to u ,,, im doing almost the same thing,my problem is when an order fails it doesnt proceed to the next order inspite of me having a error handler in place …

1. I have a service that processes a order (it does some update statement)
2.I have another service that the client call’s and send multiple orders.In that service i have a for loop that loops through all the orders
3.If i pass an order that doesnt exist in t he database the update statement in (1) fails .I however dont raise an error in (1) but it should automatically propagate to (2) right ? where i have an error handler and i have a resume action hence it should proceed to the next step right ?? which is not happening
4.After that i append the output using Insert action to a variable i created outside the for loop

hope i could explain what exactly im doing …i will send the code soon

commenter

Hi, i solved my problem by handling the error in the service that handles a single order (i.e the service where the error originated)

commenter

Hi Eric,

I want to ask you as expert something regarding wsdl fault definition:

This piece of definition we also use in our wsdl documents, but for example Oracle OSB Worskhop for osb 10g under Linux and Oxygen XML editor validate definition above is not valid and both tools say that there can be used only soap:fault element inside wsdl:fault. I didn’ try it yet directly in JDeveloper 11g, but expect that it would be valid.

On the other hand for Altova XML Spy the definition is valid.

There is also little difference in wsdl and soap schemas by w3c and oracle(for oracle i extracted wsdl.jar from jdeveloper installation). w3c wsdl 1.1 specification uses an old 2000/10/XMLSchema against 2001/XMLSchema used by oracle.

I took a look into Oxygen XML editor and it uses wsdl4j.jar library as validator. On the other hand for example JDeveloper 11g uses it’s own library.

If I take wsdl 1.1. specification schemas downloaded from http://www.w3.org/TR/wsdl into Oxygen XML editor it also says that the whole schema is not valid :-))) I didn’t try it in JDeveloper or even OSB Workshop, but seems to me like joke and don’t know where the truth lies. It points me to situation where wsdl4j used by some xml editors has some bug.

Thank for any related references or explanation.

This is little bit confusing, of course

Best regards,

Ladislav

commenter

Hi Ladislav,

I’ve never really dived into this i must say. I mostly use xmlspy to validate my wsdl/xsd resources and use those in the osb workshop tool. I never had any problems with those or with tools would generate client code against them (for example apache cxf).
You’re facing any problems at the moment ?

nitin shrivastava | February 8th, 2012 at 2:48 am
commenter

hello all, i am new in Oracle service bus, i am facing problem while i am using foreach loop to itrate some records. could anyone explain me the structure and what all parameter i have to give.

commenter

Hi, is it normal behaviour of the OSB that when your service (in my case a restfull webservice) returns a http-response-code 404 but ALSO returns something in the body (and headers content-length is not 0!!), that I get nothing in the OSB payload? This is what I getting in the logs before entering in the error handler:
Service Ref = ESB_TEST/Bindings/ws-test
URI =
Error code = BEA-380002
Error Message = Not Found
Message ID = 2377474372598800890--3d223947.136c0998260.-6e8d
Response metadata =

770
text/xml;charset=UTF-8
Wed, 18 Apr 2012 17:41:44 GMT
Apache-Coyote/1.1

3
Not Found
UTF-8
404

Payload =

>

Thanks in advance!

commenter

Hm…no idea. Will have to do some tests myself for this one

commenter

Hi Eric,

Thanks for the blogs. (I also read the other blog about generic Faults).

They were very informative.

It is a little off topic but the thing that bugs me is:

In our situation we have multiple endpoints.

If i want to have soap faults in my proxy then i need to disable application error retries in my business service. Right?

But for some soapfaults i want to retry to another endpoint. So my first idea was to implement some exception scenario that interprets the soapfaults. Do i then need to implement some retry mechanism? or is there something else possible?

Again, It is a little off topic but i hope that you want to help me out.

Thanks in advace,

Rene
Thanks in advance,

Rene

commenter

Hi Eric,

Thanks for the blogs. (I also read the other blog about generic Faults).

They were very informative.

It is a little off topic but the thing that bugs me is:

In our situation we have multiple endpoints (per Business service).

If i want to have soap faults in my proxy then i need to disable application error retries in my business service. Right?

But for some soapfaults i want to retry to another endpoint. So my first idea was to implement some exception scenario that interprets the soapfaults. Do i then need to implement some retry mechanism? or is there something else possible?

Again, It is a little off topic but i hope that you want to help me out.

Thanks in advace,

Rene

commenter

I think you need to implement this logic by yourself either in the service error handler or in some generic process.
Don’t think you can have ‘default’ conditional logic based on the type of soap fault which is getting thrown, so you need to build it yourself (but that’s more or less an assumption of me).

commenter

Hi Eric,

I am getting BEA-380002 Not Found. I am not using any special character and I have deployed the .jar files. Can you please guide me on this.

Best Regards,
Pankaj

commenter

Have you tried debug/testrun it in Eclipse, and see where in your process the problem occures ?

commenter

Hi Eric,

Thanks for your reply. I have send you the email. Can you please go thorugh it and let me know.

Best Regards,
Pankaj

[…] some examples (also explained in more detail by Eric Elzinga here ). A proxy service with this basic Error Handler will log the $fault and […]

commenter

HI Eric,

I need some help on my OSB design.

I have one osb project where source application has a queue from where we will take data and sent it to one target application db procedure. After that from target the response message will come which we need to sent to a db procedure defined in the source application. (Basically source application defined one queue to sent data to osb and defined one procedure to receive response from osb).

My design is like

(source app queue)proxy—route—routing—-(target app db proc) business service
request action of routing
log —replace —log
response action of routing
publish to second business service(source app db proc)—-under publish-replace action

Replace action are here for transformation and mapping purpose.

This design is working fine.

Now I am going to use an error handler framework which will be two different framework for request action as well as response action in the design. So if any error occur in request line one particular error message will go to source app db proc business service and if error occur in response pipeline one different error message will go to the source app db proc business service.

But here I am not able to implement two different error handler on request as well as in response but only one handler can be implemented in the routing option. So in this case this error handler will catch the error of both request as well as response and sent a common message to source app db proc business service which is not as per my requirement.

So is there any way that I can implement my requirement here in my design or I have to change all of my design to use pipeline pair instead of route-routing.

commenter

When you catch the error at service level, don’t you see in the stack some location/action at which the error occured?
You could use a globalVariable which you assign values to in the routing request/response, so when the error occures you know what the ‘last’ step has been before it went wrong.

assign “routingRequest” to globalRoutingStage (in the request pipe)
assign “routingResponse” to globalRoutingStage (in the response pipe)

are use more levels of assignments, so you can use it as some sort of tracking variable

commenter

Hi Eric, just read the comments in above blog. In my case also OSB hits a restfull webservice which returns a http-response-code 404 and error message in the body (i.e. content-length is not 0), but I get nothing in the OSB service call out response payload? This is what I getting in final response

BEA-382502

OSB Service Callout action received an error response

404

PipelinePairNode1
PipelinePairNode1_request
RouteByURI
request-pipeline

Would really appreciate any help on this.

commenter

And when you put a log activity in the service callout and log $body, you don’t get any output i assume?
You maybe have a testcase in which i can reproduce it? if not i need to create some myself 😉

commenter

Hi Eric, this is nice presentation. I am trying to build one generic error handling framework which could be used both for OSB and BPEL fault. Can you please suggest the approach. Thanks in advance.

commenter

Hi Santanu,

What’s the functionality of the error hospital ? Is it just for having a overview of all the error which occured or do you also want to be able to retry instances, etc. Because in case of the last you need to know where the error occured to be able to retry processes. So it really depends on what logic you want to implement.

commenter

Hi Eric,

I am having trouble with custom fault.

Scenario:

Error Handler is defined on service level.
On error handler I am preparing custom fault.
OWSM policy is implemented.
SOAP header have two things
1. Custom fault uses some values of custom header(is part of SOAP header)
2. wsse:Security is passed in SOAP Header

Test cases:
1. When right user, if any error occurs in proxy service. Service level error handler prepares custom fault
2. when wrong user, get excetpion to create custom header due to non-availability of custom header.

Could you please help.

BR,
Madhavendra

commenter

Hey I have to through the exception I was able to do it sucessfully.
But the error thrown i am getting it as a soap message. but I wanted to get only the message but not the whole soap message
my response message is shown below:

The invocation resulted in an error: .

soapenv:Server
enter valid role

enter valid role

PipelinePairNode1
PipelinePairNode1_request
stage2
request-pipeline

In this i want to have only the message ‘enter valid role’

Thanks in advance

commenter

Will send you an email

[…] Oracle Service Bus 11g, handling SOAP Faults – Oracle … – 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 … […]

Leave a Reply:

Name (required):
Mail (will not be published) (required):
Website:
Comment (required):
XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>