OSB: Creating meaningful SOAP exceptions

The OSB is usually used to transform and route messages. But sometimes something goes wrong and we have to return the caller an exception.

This can happen in two situations:

  • We want to create a new exception because a special situation
  • We want to create a new exception because of an exception thrown by a called service

The exceptions we want to create should be of the type soap:exception. And we want to include as much information as possible. For example information provided by the caller like user information or environment, time of the creation of the exception and id of the message the exception is a response for.

It should also be possible to create the exceptions with a few lines of code. The best solution is to create a generic XQuery constructing the exception. Because we have two use cases we create two XQuerys: FaultParameterized.xq and FaultFromFault.xq.

In a first step we add a pipeline with an assign the content of body to bodyIncoming. This is necessary because during the flow usually the content of the variable body is changed and it would not be possible to access the original incoming message.

BLOG_OSB_Exception_01

Depending on the operation called we execute a branch of the operational branch. But if caller provides a non existing operation we want to return an exception. The implementation for this situation is the FaultParameterized.xq

1 xquery version "1.0" encoding "UTF-8"; 2 (:: pragma bea:global-element-parameter parameter="$inbound" ::) 3 (:: pragma bea:global-element-parameter parameter="$bodyIncoming" ::) 4 (:: pragma bea:global-element-parameter parameter="$messageID" type="xs:token" ::) 5 (:: pragma bea:global-element-parameter parameter="$errorType" type="xs:token" ::) 6 (:: pragma bea:global-element-parameter parameter="$errorCode" type="xs:token" ::) 7 (:: pragma bea:global-element-parameter parameter="$errorMessage" type="xs:string" ::) 8 9 declare namespace con = "http://www.bea.com/wli/sb/context"; 10 declare namespace exception = "http://opitz-consulting.com/data/common/BusinessExceptionTypes/V1"; 11 declare namespace request = "http://opitz-consulting.com/data/common/RequestInformationTypes/V1"; 12 declare namespace soap = "http://schemas.xmlsoap.org/soap/envelope/"; 13 declare namespace xf = "http://opitz-consulting.com/data/common/transformations/FaultParameterized/"; 14 15 declare function xf:FaultParameterizied($inbound as element(*), $bodyIncoming as element(*), $messageID as xs:token, $errorType as xs:token, $errorCode as xs:token, $errorMessage as xs:string) as element(*) { 16 <soap:Fault> 17 <faultcode>soap:Server</faultcode> 18 <faultstring>{ $errorCode }</faultstring> 19 <detail> 20 { 21 element{ fn:expanded-QName(xs:string(namespace-uri($bodyIncoming/*[1])), concat(data($inbound/con:service/con:operation), $errorType)) } { 22 element exception:faultHeader { 23 element request:Message { 24 element request:CreationDate { current-dateTime() }, 25 element request:MessageType { "fault" }, 26 element request:MessageID { $messageID }, 27 element request:MessageVersion { "1.0" }, 28 element request:MessageReferenceID { data($bodyIncoming//request:Message/request:MessageID) } 29 }, 30 element request:Caller { 31 element request:SourceSystemName { data($bodyIncoming//request:Caller/request:SourceSystemName) }, 32 element request:Environment { data($bodyIncoming//request:Caller/request:Environment) }, 33 element request:User { 34 element request:UserID { data($bodyIncoming//request:Caller/request:User/request:UserID) } 35 } 36 }, 37 element request:Operation { 38 element request:Operation { data($inbound/con:service/con:operation) } 39 }, 40 element request:Response { 41 element request:ProcessingInformation { 42 element request:ServerName { "unknown" }, 43 element request:InstanceID { "unknown" }, 44 element request:ExecutionContextID { "unknown" } 45 46 } 47 } 48 }, 49 element exception:Fault { 50 element exception:ErrorCode { $errorCode } , 51 element exception:ErrorMessage { $errorMessage } 52 } 53 } 54 } 55 </detail> 56 </soap:Fault> 57 }; 58 59 declare variable $inbound as element(*) external; 60 declare variable $bodyIncoming as element(*) external; 61 declare variable $messageID as xs:token external; 62 declare variable $errorType as xs:token external; 63 declare variable $errorCode as xs:token external; 64 declare variable $errorMessage as xs:string external; 65 66 xf:FaultParameterizied($inbound, $bodyIncoming, $messageID, $errorType, $errorCode, $errorMessage) 67

We insert the replace into the default branch.

BLOG_OSB_Exception_02

And provide the needed parameters.

BLOG_OSB_Exception_03

 

Now we can try to make a call to the non-existing dummyOperation with this request:

1 <message:dummyOperation xmlns:message="http://opitz-consulting.com/interfaces/ProtokollTestMessages/V1"> 2 <request:Header xmlns:request="http://opitz-consulting.com/data/common/RequestInformationTypes/V1"> 3 <request:Message> 4 <request:CreationDate>2014-07-17T17:33:57.544+02:00</request:CreationDate> 5 <request:MessageType>request</request:MessageType> 6 <request:MessageID>1234345667890</request:MessageID> 7 <request:MessageVersion>1.0</request:MessageVersion> 8 </request:Message> 9 <request:Caller> 10 <request:SourceSystemName>testSystem</request:SourceSystemName> 11 <request:Environment>DEV</request:Environment> 12 <request:User> 13 <request:UserID>testUser</request:UserID> 14 </request:User> 15 </request:Caller> 16 </request:Header> 17 </message:dummyOperation>

We get this error response including some information we sent with the request:

1 <?xml version="1.0"?> 2 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 3 <soap:Header xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"/> 4 <soapenv:Body> 5 <soapenv:Fault> 6 <faultcode>soap:Server</faultcode> 7 <faultstring>ERROR_UNKNOWN_OPERATION</faultstring> 8 <detail> 9 <v1:UnknownOperation xmlns:v1="http://opitz-consulting.com/interfaces/ProtokollTestMessages/V1"> 10 <v11:faultHeader xmlns:v11="http://opitz-consulting.com/data/common/BusinessExceptionTypes/V1"> 11 <v12:Message xmlns:v12="http://opitz-consulting.com/data/common/RequestInformationTypes/V1"> 12 <v12:CreationDate>2014-07-17T17:56:38.249+02:00</v12:CreationDate> 13 <v12:MessageType>fault</v12:MessageType> 14 <v12:MessageID>5480523608781123005--3df23bc.1471b27a72f.-7f99</v12:MessageID> 15 <v12:MessageVersion>1.0</v12:MessageVersion> 16 <v12:MessageReferenceID>1234345667890</v12:MessageReferenceID> 17 </v12:Message> 18 <v12:Caller xmlns:v12="http://opitz-consulting.com/data/common/RequestInformationTypes/V1"> 19 <v12:SourceSystemName>testSystem</v12:SourceSystemName> 20 <v12:Environment>DEV</v12:Environment> 21 <v12:User> 22 <v12:UserID>testUser</v12:UserID> 23 </v12:User> 24 </v12:Caller> 25 <v12:Operation xmlns:v12="http://opitz-consulting.com/data/common/RequestInformationTypes/V1"> 26 <v12:Operation/> 27 </v12:Operation> 28 <v12:Response xmlns:v12="http://opitz-consulting.com/data/common/RequestInformationTypes/V1"> 29 <v12:ProcessingInformation> 30 <v12:ServerName>unknown</v12:ServerName> 31 <v12:InstanceID>unknown</v12:InstanceID> 32 <v12:ExecutionContextID>unknown</v12:ExecutionContextID> 33 </v12:ProcessingInformation> 34 </v12:Response> 35 </v11:faultHeader> 36 <v11:Fault xmlns:v11="http://opitz-consulting.com/data/common/BusinessExceptionTypes/V1"> 37 <v11:ErrorCode>ERROR_UNKNOWN_OPERATION</v11:ErrorCode> 38 <v11:ErrorMessage>The requested operation is not implemented</v11:ErrorMessage> 39 </v11:Fault> 40 </v1:UnknownOperation> 41 </detail> 42 </soapenv:Fault> 43 </soapenv:Body> 44 </soapenv:Envelope> 45

 

For the route it is possible to implement an error handler. In the error handler a correct exception should be created adding the additional information from the thrown error.  In this situation we use FaultFromFault.xq

1 xquery version "1.0" encoding "UTF-8"; 2 (:: pragma bea:global-element-parameter parameter="$inbound" ::) 3 (:: pragma bea:global-element-parameter parameter="$bodyIncoming" ::) 4 (:: pragma bea:global-element-parameter parameter="$messageID" type="xs:string" ::) 5 (:: pragma bea:global-element-parameter parameter="$errorType" type="xs:string" ::) 6 (:: pragma bea:global-element-parameter parameter="$fault" ::) 7 (:: pragma bea:global-element-parameter parameter="$body" ::) 8 9 declare namespace con = "http://www.bea.com/wli/sb/context"; 10 declare namespace conDetail = "http://www.bea.com/wli/sb/stages/transform/config"; 11 declare namespace exception = "http://opitz-consulting.com/data/common/BusinessExceptionTypes/V1"; 12 declare namespace request = "http://opitz-consulting.com/data/common/RequestInformationTypes/V1"; 13 declare namespace soap = "http://schemas.xmlsoap.org/soap/envelope/"; 14 declare namespace xf = "http://opitz-consulting.com/data/common/transformations/FaultFromFault/"; 15 16 17 declare function xf:FaultFromFault($inbound as element(*), $bodyIncoming as element(*), $messageID as xs:string, $errorType as xs:string, $fault as element(*), $body as element(*)) as element(*) { 18 <soap:Fault> { 19 element faultcode { 20 if ($fault/con:details//conDetail:faultcode) then 21 data($fault/con:details//conDetail:faultcode) 22 else 23 "soap:Server" 24 }, 25 element faultstring { 26 if ($fault/con:details//conDetail:faultstring) then 27 data($fault/con:details//conDetail:faultstring) 28 else 29 data($fault/con:errorCode) 30 }, 31 element detail { 32 element{ fn:expanded-QName(xs:string(namespace-uri($bodyIncoming/*[1])), concat(data($inbound/con:service/con:operation), $errorType)) } { 33 element exception:faultHeader { 34 element request:Message { 35 element request:CreationDate { current-dateTime() }, 36 element request:MessageType { "fault" }, 37 element request:MessageID { $messageID }, 38 element request:MessageVersion { "1.0" }, 39 element request:MessageReferenceID { data($bodyIncoming//request:Message/request:MessageID) } 40 }, 41 element request:Caller { 42 element request:SourceSystemName { data($bodyIncoming//request:Caller/request:SourceSystemName) }, 43 element request:Environment { data($bodyIncoming//request:Caller/request:Environment) }, 44 element request:User { 45 element request:UserID { data($bodyIncoming//request:Caller/request:User/request:UserID) } 46 } 47 }, 48 element request:Operation { 49 element request:Operation { data($inbound/con:service/con:operation) } 50 }, 51 element request:Response { 52 element request:ProcessingInformation { 53 element request:ServerName { "unknown" }, 54 element request:InstanceID { "unknown" }, 55 element request:ExecutionContextID { "unknown" } 56 57 } 58 } 59 }, 60 element exception:Fault 61 { 62 element exception:ErrorCode { 63 if ($body//exception:Fault/exception:ErrorCode) then 64 data($body//exception:Fault/exception:ErrorCode) 65 else 66 data($fault/con:errorCode) 67 }, 68 element exception:ErrorMessage { 69 if ($fault/con:details//conDetail:faultstring) then 70 data($fault/con:details//conDetail:faultstring) 71 else if ($body//exception:Fault/exception:ErrorMessage) then 72 data($body//exception:Fault/exception:ErrorMessage) 73 else if ($body//soap:Fault/faultstring) then 74 data($body//soap:Fault/faultstring) 75 else 76 data($fault/con:reason) 77 }, 78 element exception:ErrorDetail { 79 $fault/con:details, 80 $fault/con:location 81 } 82 } 83 } 84 } 85 } </soap:Fault> 86 }; 87 88 declare variable $inbound as element(*) external; 89 declare variable $bodyIncoming as element(*) external; 90 declare variable $messageID as xs:string external; 91 declare variable $errorType as xs:string external; 92 declare variable $fault as element(*) external; 93 declare variable $body as element(*) external; 94 95 xf:FaultFromFault($inbound, $bodyIncoming, $messageID, $errorType, $fault, $body) 96

We insert the replace into the error handler.

BLOG_OSB_Exception_04

And provide the needed parameters.

BLOG_OSB_Exception_05

 

Now we can try to make a call to the operation getServiceInfo, which makes a callout to a non existing service, with this request:

1 <message:getServiceInfoRequest xmlns:message="http://opitz-consulting.com/interfaces/ProtokollTestMessages/V1"> 2 <request:Header xmlns:request="http://opitz-consulting.com/data/common/RequestInformationTypes/V1"> 3 <request:Message> 4 <request:CreationDate>2014-07-17T17:33:57.544+02:00</request:CreationDate> 5 <request:MessageType>request</request:MessageType> 6 <request:MessageID>1234345667890</request:MessageID> 7 <request:MessageVersion>1.0</request:MessageVersion> 8 </request:Message> 9 <request:Caller> 10 <request:SourceSystemName>testSystem</request:SourceSystemName> 11 <request:Environment>DEV</request:Environment> 12 <request:User> 13 <request:UserID>testUser</request:UserID> 14 </request:User> 15 </request:Caller> 16 </request:Header> 17 </message:getServiceInfoRequest> 18

We get this error response including some information we sent with the request:

1 <?xml version="1.0"?> 2 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 3 <soap:Header xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"/> 4 <soapenv:Body> 5 <soapenv:Fault> 6 <faultcode>soap:Server</faultcode> 7 <faultstring>BEA-380002</faultstring> 8 <detail> 9 <v1:getServiceInfoUnexpectedError xmlns:v1="http://opitz-consulting.com/interfaces/ProtokollTestMessages/V1"> 10 <v11:faultHeader xmlns:v11="http://opitz-consulting.com/data/common/BusinessExceptionTypes/V1"> 11 <v12:Message xmlns:v12="http://opitz-consulting.com/data/common/RequestInformationTypes/V1"> 12 <v12:CreationDate>2014-07-17T18:01:32.055+02:00</v12:CreationDate> 13 <v12:MessageType>fault</v12:MessageType> 14 <v12:MessageID>5480523608781123005--3df23bc.1471b27a72f.-7f95</v12:MessageID> 15 <v12:MessageVersion>1.0</v12:MessageVersion> 16 <v12:MessageReferenceID>1234345667890</v12:MessageReferenceID> 17 </v12:Message> 18 <v12:Caller xmlns:v12="http://opitz-consulting.com/data/common/RequestInformationTypes/V1"> 19 <v12:SourceSystemName>testSystem</v12:SourceSystemName> 20 <v12:Environment>DEV</v12:Environment> 21 <v12:User> 22 <v12:UserID>testUser</v12:UserID> 23 </v12:User> 24 </v12:Caller> 25 <v12:Operation xmlns:v12="http://opitz-consulting.com/data/common/RequestInformationTypes/V1"> 26 <v12:Operation>getServiceInfo</v12:Operation> 27 </v12:Operation> 28 <v12:Response xmlns:v12="http://opitz-consulting.com/data/common/RequestInformationTypes/V1"> 29 <v12:ProcessingInformation> 30 <v12:ServerName>unknown</v12:ServerName> 31 <v12:InstanceID>unknown</v12:InstanceID> 32 <v12:ExecutionContextID>unknown</v12:ExecutionContextID> 33 </v12:ProcessingInformation> 34 </v12:Response> 35 </v11:faultHeader> 36 <v11:Fault xmlns:v11="http://opitz-consulting.com/data/common/BusinessExceptionTypes/V1"> 37 <v11:ErrorCode>BEA-380002</v11:ErrorCode> 38 <v11:ErrorMessage>www.google.com</v11:ErrorMessage> 39 <v11:ErrorDetail> 40 <con:location xmlns:con="http://www.bea.com/wli/sb/context"> 41 <con:node>routeGetServiceInfo</con:node> 42 <con:path>request-pipeline</con:path> 43 </con:location> 44 </v11:ErrorDetail> 45 </v11:Fault> 46 </v1:getServiceInfoUnexpectedError> 47 </detail> 48 </soapenv:Fault> 49 </soapenv:Body> 50 </soapenv:Envelope> 51

 

Bernhard Mähr @ OPITZ-CONSULTING published at http://thecattlecrew.wordpress.com/

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s