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.
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
1xquery 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 9declare namespace con = „http://www.bea.com/wli/sb/context“; 10declare namespace exception = „http://opitz-consulting.com/data/common/BusinessExceptionTypes/V1“; 11declare namespace request = „http://opitz-consulting.com/data/common/RequestInformationTypes/V1“; 12declare namespace soap = „http://schemas.xmlsoap.org/soap/envelope/“; 13declare namespace xf = „http://opitz-consulting.com/data/common/transformations/FaultParameterized/“; 1415declare 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“ } 4546 } 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}; 5859declare variable $inbound as element(*) external; 60declare variable $bodyIncoming as element(*) external; 61declare variable $messageID as xs:token external; 62declare variable $errorType as xs:token external; 63declare variable $errorCode as xs:token external; 64declare variable $errorMessage as xs:string external; 6566xf:FaultParameterizied($inbound, $bodyIncoming, $messageID, $errorType, $errorCode, $errorMessage) 67
We insert the replace into the default branch.
And provide the needed parameters.
Now we can try to make a call to the non-existing dummyOperation with this request:
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
1xquery 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 9declare namespace con = „http://www.bea.com/wli/sb/context“; 10declare namespace conDetail = „http://www.bea.com/wli/sb/stages/transform/config“; 11declare namespace exception = „http://opitz-consulting.com/data/common/BusinessExceptionTypes/V1“; 12declare namespace request = „http://opitz-consulting.com/data/common/RequestInformationTypes/V1“; 13declare namespace soap = „http://schemas.xmlsoap.org/soap/envelope/“; 14declare namespace xf = „http://opitz-consulting.com/data/common/transformations/FaultFromFault/“; 151617declare 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“ } 5657 } 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}; 8788declare variable $inbound as element(*) external; 89declare variable $bodyIncoming as element(*) external; 90declare variable $messageID as xs:string external; 91declare variable $errorType as xs:string external; 92declare variable $fault as element(*) external; 93declare variable $body as element(*) external; 9495xf:FaultFromFault($inbound, $bodyIncoming, $messageID, $errorType, $fault, $body) 96
We insert the replace into the error handler.
And provide the needed parameters.
Now we can try to make a call to the operation getServiceInfo, which makes a callout to a non existing service, with this request: