soap-dtc-core tutorial

Prerequisites

Before we get started, you will need to obtain the library. If you opt to get it through Maven2, the dependencies will be obtained automatically for you. If you opt for the binaries distribution, you will find the Jars of the required libraries in lib/.

We do not make any special assumption about the IDE that you use.

Core library overview

Constructing a SOAP message

The SoapMessage class is a thin front-end to a Dom4J document that represents the SOAP message as an XML document. Therefore, we recommend that you first get familiar with Dom4J first. Fortunately, it is a very easy API to deal with!

SoapMessage offers several constructors, but you will obviously instanciate it the most simple way:

SoapMessage message = new SoapMessage();

If you have a ready to use SOAP message as a resource, you can also read it directly through the SoapMessageUtils class:

SoapMessage message = SoapMessageUtils.readSoapMessageFromStream(
getClass().getResourceAsStream("soap-message.xml"));

If you use the default constructor, you will have a SOAP document with an empty header element, and an empty body element. You can access the specific XML elements of a SOAP document by using accessors:

Element header = message.getHeaderElement();
Element body = message.getBodyElement();

You can also get the whole XML document:

Document soapDocument = message.getSoapDocument();

Obviously, you will want to populate the content of your SOAP message. Simply use the Dom4J API to construct XML elements, then add it to your message as follows.

Adding a header or body element is as simple as:

message.addHeaderElement(headerElement1);
message.addHeaderElement(headerElement2);
message.addBodyElement(bodyElement);

This will add two header elements and one body element to the SOAP message. Remember that the body element of a SOAP message can have several children.

Finally, you may want to use the env:mustUnderstand attribute for SOAP headers, to explicitly mentionned if they must absolutely be processed or not. Simply use this method:

addHeaderElement(Element element, boolean mustUnderstand)

and it will automatically add a env:mustUnderstand attribute to the header.

Communicate with a web service

Now that you know how to build a SOAP message, you are ready to communicate with SOAP-based web services. In this example, we will show how to communicate with a HTTP-binded web service located at http://server/services/dtc.

The HttpSoapTransport does just that, and uses commons-httpclient under the hood. In most cases everything will run out of the box, but in certain cases (for example due to a proxy), you might need to tweak how the HTTP connection can be made. We provide accessors to the commons-httpclient configuration so that you can just do that.

This class supports the send/receive and receive message exchange patterns. Here’s how it works.

HttpSoapTransport soapTransport = new HttpSoapTransport();
 
SoapMessage response = soapTransport.sendReceive(
    "http://server/services/dtc", message, "update");
 
response = soapTransport.receive("http://server/services/dtc",
    "latest-quotes");

For each method, the last parameter is a soap action value that some services use for dispatching purposes. As standards make it optional, you can simply pass null here if the service you invoke doesn’t use it.

HttpSoapTransport also supports asynchronous versions of the two methods above. For example to asynchronously send then receive a SOAP message, you can do the following:

soapTransport.asyncSendReceive("http://server/services/dtc",
    message, null,
    new IAsyncSoapMessageHandler() {
        public void handleAsyncResponse(SoapMessage  response)
        {
            // Handle the response
        }
 
        public void handleAsyncTransportException(SoapTransportException exception)
        {
            // Handle the exception
        }
});

The IAsynSoapMessageHandler methods will be called from another thread.

Handling SOAP faults

The code of the previous section can throw a SoapTransportException. It is a simple subclass of Exception, and it can contain a SOAP message with a fault. If the error is at a lower level (for example a network failure), then it will contain a nested exception such as IOException.

Here is an example of catching such an exception that has been extracted from our tests suite.

try
{
    response = soapTransport.sendReceive("http://localhost:8085/dtc/iya", message, null);
    fail("There should have been an exception here!");
}
catch (SoapTransportException e)
{
    SoapMessage msg = e.getSoapMessageWithFault();
    assertNotNull(msg);
    assertTrue(msg.containsFault());
    // (...)
}

As you may have guessed, a SoapTransportException provides a SOAP message with a fault through getSoapMessageWithFault(). Also, the SoapMessage class defines a containsFault method to check if a SOAP message has a fault as body. Finally, you can access a fault element directly:

if (msg.containsFault())
{
    Element fault = msg.getFaultElement();
    // (...)
}

Generating SOAP faults

A SOAP fault is just a normalized XML subtree in a SOAP body. We thought it could be a good idea to make your life simpler here as well! That’s why we have created the SoapFault class that helps generating a valid SOAP fault XML element. Here is an example.

SoapFault fault = new SoapFault();
fault.setCode(SoapConstants.SOAP12_FAULT_SENDER, "m:MessageTimeout", null);
fault.addReason("en", "Sender Timeout");
Element detailElement = documentFactory.createElement("m:MaxTime", "urn:foo");
detailElement.setText("P5M");
fault.setDetail(detailElement);
 
message.addBodyElement(fault.toXmlElement());

That's it!

Communicating with SOAP-based web services is as simple as that with soap-dtc-core. Just a few straightforward classes that leverage on proven third-party libraries and that’s it, without even having to generate code :-)

soap-dtc-core.txt · Last modified: 2007/05/16 08:34
 
 
 
Recent changes RSS feed Creative Commons License Valid XHTML 1.0 Valid CSS Driven by DokuWiki