Schema Validation and Error Handling

Sample Number

203

Level

Introductory

Description

This sample demonstrates the schema validation and error handling capabilities of the UltraESB

Use Case

I want to validate the request messages with XML payloads over an XSD schema in the UltraESB before further processing it. Additionally I want the UltraESB to perform error handling and recovery of a particular flow defined in the configuration and direct the error cases into another flow treating it as an error handler.

Sample Configuration

The configuration to do schema validation is straight forward using the UltraESB Mediation API, in particular the validate method call of the XMLSupport.

Proxy service configuration for schema validation

 1<u:proxy id="soap-proxy-1">
 2  <u:transport id="http-8280"/>
 3  <u:target inDestination="stockquote" outDestination="response">
 4    <u:inSequence onErrorInvoke="sequenceErrorHandler">
 5      <u:java><![CDATA[
 6          String[] schemas = {"samples/resources/stock.xsd", "samples/resources/common.xsd"};
 7          String[][] ns = {{"soap", "http://soap.services.samples/"}};
 8          mediation.getXMLSupport().validate(msg, schemas, "//soap:getQuote", ns);
 9      ]]></u:java>
10    </u:inSequence>
11  </u:target>
12</u:proxy>

This configuration consist of a SOAP proxy service named "soap-proxy-1" that specifies its inDestination and outDestination by reference to the re-usable endpoints "stockquote" and "response". The inSequence is assigned another sequence"sequenceErrorHandler" to be invoked on an error. Thus, if the request fails schema validation, the error handler sequence will be invoked to return a SOAP fault.

The Schema validation can take in multiple XSD files - e.g. when one XSD imports or includes others. Refer to the API documentation for more details. The element to be validated is extracted from an optional XPath expression if specified.

Note
The underlying Xerces parser is sensitive to the order of schemas and hence the schemas need to be specified in-order

The sequence error handler is configured to send back a fault to the client as follows;

Sequence error handler configuration

1<u:sequence id="sequenceErrorHandler">
2  <u:java><![CDATA[
3      System.out.println("Error handler called");
4      mediation.getSOAPSupport().setPayloadToSOAP11Fault(msg, null, "Validation Failed", msg.getLastException().toString());
5      mediation.sendResponseAndDrop(msg, 500);
6  ]]></u:java>
7</u:sequence>

This error handler is a sequence level error handler, which gets invoked for any error in mediation within the sequence. It is also possible to specify a service level error handler, which gets invoked for any error within the scope of that service, provided that there is no other error handler defined in the inner scope (such as in a sequence). Service level error handlers can be configured as follows;

Proxy service configuration with a service level error handler

 1<u:proxy id="soap-proxy-2">
 2  <u:transport id="http-8280"/>
 3  <u:target inDestination="stockquote" outDestination="response" errorSequence="serviceErrorHandler">
 4    <u:inSequence>
 5      <u:java><![CDATA[
 6          String[][] ns = {{"soap", "http://soap.services.samples/"}};
 7          if (mediation.getXMLSupport().filter(msg, "//soap:getQuote/request/symbol", ns, "ADRT")) {
 8              mediation.sendToEndpoint(msg, "stockquote");
 9          } else {
10              mediation.sendToEndpoint(msg, "stockquote-err");
11          }
12      ]]></u:java>
13    </u:inSequence>
14  </u:target>
15</u:proxy>

The above configuration defines a proxy service named "soap-proxy-2" which will test the stock symbol, and forward requests for the symbol "ADRT" to the valid endpoint, and any other symbol to an invalid endpoint. The configuration specifies a service level error handler and the invalid endpoint send should trigger the service error handler.

The service error handler again is a sequence configured to send back a fault to the client as follows;

Service level error handler

1<u:sequence id="serviceErrorHandler">
2  <u:java><![CDATA[
3      System.out.println("Service error handler called");
4      mediation.getSOAPSupport().setPayloadToSOAP11Fault(msg, null, "Generic service error", msg.getLastException().toString());
5      mediation.sendResponseAndDrop(msg, 500);
6  ]]></u:java>
7</u:sequence>

Note that the error messages in the 2 cases, sequence error handler and service error handler is configured to be different, so that the distinct error for the 2 cases can be identified easily.

Note
For the simplicity the complete configuration is not displayed here, you may look at the complete configuration either from the binary distribution under samples/conf/ultra-sample-203.xml, or from the sample 203 configuration of the source tag.

In Action

To run the example, start the UltraESB sample configuration 203 via the ToolBox or on the command line as follows.

Running the sample from startup script

$ cd /opt/ultraesb-2.6.1/bin
$ ./ultraesb.sh -sample 203

Now start the SOA Toolbox, and fire-up the sample Jetty server on port 9000 that holds the SimpleStockQuoteService acting as the back-end service for testing.

Use the same SOA Toolbox to open the HTTP/S client on a separate tab and issue a Preset "1" request to the URL http://localhost:8280/service/soap-proxy-1 for which you will get a successful response. Now edit the request such that its not well formed XML, and you will get and error message as follows;

Fault response for the invalid request

HTTP/1.0 500 Internal Server Error
Host: localhost:8280
SOAPAction: urn:getQuote
User-Agent: AdroitLogic (http://adroitlogic.org) - SOA Toolbox/1.5.0
Content-Type: text/xml; charset=UTF-8
Date: Thu, 09 Feb 2012 17:06:55 GMT
Server: UltraESB/2.6.1
Content-Length: 342
Connection: close
 
<S11:Envelope xmlns:S11="http://schemas.xmlsoap.org/soap/envelope/">
  <S11:Body>
    <S11:Fault>
      <faultcode>S11:Server</faultcode>
      <faultstring>Validation Failed</faultstring>
      <detail>Error converting org.adroitlogic.ultraesb.core.format.RawFileMessage to a DOM message, with error code -1 : Generic error</detail>
    </S11:Fault>
  </S11:Body>
</S11:Envelope>

Note that this response is being generated by the sequence error handler as expected.

Now to test the service level error handler and the filtering proxy service, send the same above request to the http://localhost:8280/service/soap-proxy-2 proxy service, to which you should get a valid response as the symbol used in the request is ADRT. However, if you change the symbol from ADRT to something else you will be able to see the service level error handler gets invoked because of the non existing endpoint being called and a fault thrown back to the client as shown below;

Response from the service level error handler

HTTP/1.0 500 Internal Server Error
Host: localhost:8280
SOAPAction: urn:getQuote
User-Agent: AdroitLogic (http://adroitlogic.org) - SOA Toolbox/1.5.0
Content-Type: text/xml; charset=UTF-8
Date: Thu, 09 Feb 2012 17:16:57 GMT
Server: UltraESB/2.6.1
Content-Length: 314
Connection: close
 
<S11:Envelope xmlns:S11="http://schemas.xmlsoap.org/soap/envelope/">
  <S11:Body>
    <S11:Fault>
      <faultcode>S11:Server</faultcode>
      <faultstring>Generic service error</faultstring>
      <detail>Endpoint stockquote-err failed, with error code 101503 : Connect attempt to server failed</detail>
    </S11:Fault>
  </S11:Body>
</S11:Envelope>

This error message confirms the invocation of the service level error handler and the content based filtering capabilities of the UltraESB.

Related Samples

Sample Number

Sample Title

201

Proxying SOAP Messages

In this topic
In this topic
Contact Us