Skip to main content

Tip: Send and receive SOAP messages with SAAJ

Java API automates many of the steps required in generating and sending messages manually

Nicholas Chase (nicholas@nicholaschase.com), President, Chase and Chase, Inc.
Photo of Nicholas Chase
Nicholas Chase, a Studio B author, has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, and an Oracle instructor. More recently, he was the Chief Technology Officer of Site Dynamics Interactive Communications in Clearwater, Florida, USA, and is the author of four books on Web development, including XML Primer Plus (Sams). He loves to hear from readers and can be reached at nicholas@nicholaschase.com.

Summary:  In this tip, author and developer Nicholas Chase shows you how to use the SOAP with Attachments API for Java (SAAJ) to simplify the process of creating and sending SOAP messages.

View more content in this series

Date:  22 Jan 2008 (Published 10 Jul 2003)
Level:  Intermediate
Activity:  16155 views

The foundation of Web services lies in the sending and receiving of messages in a standard format so that all systems can understand them. Typically, that format is SOAP. A SOAP message can be generated and sent manually, but the SOAP with Attachments API for Java (SAAJ) -- an offshoot of the Java API for XML Messaging (JAXM) -- automates many of the required steps, such as creating connections or creating and sending the actual messages. This tip chronicles the creation and sending of a synchronous SOAP message.

The process involves five steps:

  1. Creating a SOAP connection
  2. Creating a SOAP message
  3. Populating the message
  4. Sending the message
  5. Retrieving the reply

SAAJ is available as part of the Java Web Services Developer Pack 1.2 (see Resources). This package also includes a copy of the Tomcat Web server (so you can host your own service) and sample applications.

Installation issues

Setting up the Java Web Services Developer Pack 1.2 is easy -- as long as you send your messages through the included Tomcat Web server. To send messages through a standalone application, as I do here, you need to take the following steps:

  1. Download the JWSDP 1.2 from http://java.sun.com/webservices/downloads/webservicespack.html.
  2. Install it according to the directions.
  3. If you're using Java 1.4, you need to override the XML-related classes provided with it. Create the following directory:
    <JAVA_HOME>/jre/lib/endorsed
    and copy the files from:
    <JWSDP_HOME>/jaxp/lib/endorsed
    into it. (JAVA_HOME and JWSDP_HOME refer to your Java installation and your JWSDP installation, respectively.)
  4. Add the following files to your classpath:
    • <JWSDP_HOME>/saaj/lib/saaj-api.jar
    • <JWSDP_HOME>/saaj/lib/saaj-impl.jar
    • <JWSDP_HOME>/jwsdp-shared/lib/commons-logging.jar
    • <JWSDP_HOME>/jwsdp-shared/lib/mail.jar
    • <JWSDP_HOME>/jwsdp-shared/lib/activation.jar
    • <JWSDP_HOME>/jaxp/lib/endorsed/dom.jar
    • <JWSDP_HOME>/jaxp/lib/endorsed/xercesImpl.jar
    • <JWSDP_HOME>/jaxp/lib/endorsed/sax.jar
    • <JWSDP_HOME>/jaxp/lib/endorsed/xalan.jar

Now you should be able to send a message from anywhere on your system using a standalone program.


The structure of a SOAP message

I'll start by showing you the structure of the message itself. A basic SOAP message consists of an envelope with two main parts: the header and the body. The application determines how these parts are used, but the overall message must follow a specific XML structure, such as:


Listing 1. A sample SOAP message
                
                <SOAP-ENV:Envelope 
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" 
        xmlns:xsd="http://www.w3.org/1999/XMLSchema"> 
    <SOAP-ENV:Header />
    <SOAP-ENV:Body> 
        <ns1:getPrice xmlns:ns1="urn:xmethods-BNPriceCheck" 
             SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 
                  <isbn xsi:type="xsd:string">0672324229</isbn> 
        </ns1:getPrice> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 
            

Here, the header is empty and the body contains the payload, or the message to be delivered. In this case, it's a message requesting the price of a book.

Notice the structure of the message. The Envelope contains the Header and Body elements, and all three are part of the http://schemas.xmlsoap.org/soap/envelope/ namespace. The application sends the message using a SOAPConnection.


Creating the connection and the message

The first step is to create the overall class and the connection:


Listing 2. Create the connection
                import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPConnection;

public class SOAPTip {
    
   public static void main(String args[]) {
        
      try {
      
         //First create the connection
         SOAPConnectionFactory soapConnFactory = 
                            SOAPConnectionFactory.newInstance();
         SOAPConnection connection = 
                             soapConnFactory.createConnection();
         


         //Close the connection            
         connection.close();
            
        } catch(Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

The application can send SOAP messages directly using a SOAPConnection, which is now part of the SAAJ package, or indirectly using a messaging provider, which remains in the JAXM package. In this case, the application creates the SOAPConnection object using a factory.

A factory also creates the message itself:


Listing 3. Creating the message object
                import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPBody;

public class SOAPTip {
    
   public static void main(String args[]) {
        
      try {
     
         //First create the connection
         SOAPConnectionFactory soapConnFactory = 
                            SOAPConnectionFactory.newInstance();
         SOAPConnection connection = 
                             soapConnFactory.createConnection();
         
         //Next, create the actual message
         MessageFactory messageFactory = MessageFactory.newInstance();
         SOAPMessage message = messageFactory.createMessage();
         
         //Create objects for the message parts            
         SOAPPart soapPart =     message.getSOAPPart();
         SOAPEnvelope envelope = soapPart.getEnvelope();
         SOAPBody body =         envelope.getBody();


         //Close the connection            
         connection.close();
            
        } catch(Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

Version differences

If you've using another version of SAAJ, such as the Axis 1.2 beta SAAJ library, you may need to use addBodyElement instead of addChildElement.

First, you create the message itself by using the MessageFactory. This message already contains empty versions of the basic parts, such as the envelope and header. The SOAPPart contains the envelope, and the envelope contains the body. Create references to the needed objects, such as the SOAPBody.

Next, populate the SOAPBody:


Listing 4. Populating the body
                ...
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;

public class SOAPTip {
    
   public static void main(String args[]) {
        
      try {
...
         //Create objects for the message parts            
         SOAPPart soapPart =     message.getSOAPPart();
         SOAPEnvelope envelope = soapPart.getEnvelope();
         SOAPBody body =         envelope.getBody();

        //Populate the body
        //Create the main element and namespace
        SOAPElement bodyElement = 
                  body.addChildElement(envelope.createName("getPrice" , 
                                                                "ns1", 
                                          "urn:xmethods-BNPriceCheck"));
        //Add content
        bodyElement.addChildElement("isbn").addTextNode("0672324229");

        //Save the message
        message.saveChanges();


        //Check the input
        System.out.println("\nREQUEST:\n");
        message.writeTo(System.out);
        System.out.println();


         //Close the connection            
         connection.close();
            
        } catch(Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

The body of the SOAP message is just like any other XML element in that you can add a child element, such as getPrice. You can then add the isbn element and its text node just as you might with a typical DOM element.

With SAAJ you also have the opportunity to directly create the SOAPPart of the message using an external file. For example, the file prepped.msg contains the XML structure in the first listing, and can be called in lieu of building the document manually:


Listing 5. Creating the message from an external file
                ...
import javax.xml.soap.SOAPElement;

import java.io.FileInputStream;
import javax.xml.transform.stream.StreamSource;

public class SOAPTip {
    
   public static void main(String args[]) {
...
         //Create objects for the message parts            
         SOAPPart soapPart =     message.getSOAPPart();
         SOAPEnvelope envelope = soapPart.getEnvelope();
         SOAPBody body =         envelope.getBody();

         //Populate the Message
        StreamSource preppedMsgSrc = new StreamSource( 
                 new FileInputStream("prepped.msg"));
        soapPart.setContent(preppedMsgSrc);

         //Save the message
         message.saveChanges();
...
    }
}

The StreamSource class is typically used as part of an XSL Transformation, but here you can use it simply to obtain the FileInputStream. The result is a SOAP message that's ready to send.


Sending the message

With a synchronous message, sending the SOAP message and receiving a reply take place in a single step:


Listing 6. Sending the message
                ...
public class SOAPTip {
    
   public static void main(String args[]) {
        
...
         //Check the input
         System.out.println("\nREQUEST:\n");
         message.writeTo(System.out);
         System.out.println();

        //Send the message and get a reply   
            
        //Set the destination
        String destination = 
            "http://services.xmethods.net:80/soap/servlet/rpcrouter";
        //Send the message
        SOAPMessage reply = connection.call(message, destination);

         //Close the connection            
         connection.close();         
...
    }
}

The SOAPAction header

Depending on the web service you're accessing, you might get an error requiring you to send the SOAPAction header in order to identify the service. You can do this by setting the MIMEHeaders on the message, like so:


MimeHeaders headers = message.getMimeHeaders();
headers.addHeader("SOAPAction", "urn:requiredSOAPAction");


The actual message is sent using the call() method, which takes the message itself and a destination as arguments and returns a second SOAPMessage as a reply. In earlier versions of JAXM, the destination had to be an Endpoint object or a URLEndpoint, but now it simply has to be an object. This example uses the "Book price checker" Web service hosted by XMethods, which returns the price of the book whose ISBN is listed in the request.

The call() method blocks until it receives the returned SOAPMessage.


The response

The returned SOAPMessage, reply, is a SOAP message in the same form as the message sent, and as such can be manipulated just like any other XML message. SOAP allows you to transform the reply directly using XSLT:


Listing 7. Reading the response
                ...
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.Source;

import javax.xml.transform.stream.StreamResult;

public class SOAPTip {
    
   public static void main(String args[]) {
        
      try {
      
...
         //Send the message
         SOAPMessage reply = connection.call(message, destination);

        //Check the output
        System.out.println("\nRESPONSE:\n");
        //Create the transformer
        TransformerFactory transformerFactory = 
                           TransformerFactory.newInstance();
        Transformer transformer = 
                        transformerFactory.newTransformer();
        //Extract the content of the reply
        Source sourceContent = reply.getSOAPPart().getContent();
        //Set the output for the transformation
        StreamResult result = new StreamResult(System.out);
        transformer.transform(sourceContent, result);
        System.out.println();

         //Close the connection            
         connection.close();
...            
     }
}

Create the Transformer object as you would in any XSLT application. In this case, you just want to output the content, so there's no stylesheet. Here, the content itself is the entire SOAP part of the message (as opposed to the SOAP message itself, which might include attachments). You could also extract the envelope and body before processing. The result in this case is simply System.out, but can be any choice normally available to a transformation. Transform as usual.


Figure 1. SOAP request and response
Request and response

Next steps

This simple application just outputs the received message, but you can just as easily extract the information from the XML document. Also, while this tip demonstrates the synchronous sending and receiving of messages, the JAXM API, available as an optional download, allows for the use of a messaging provider for asynchronous delivery through the use of a ProviderConnection object rather than a SOAPConnection. The provider holds the message until it is delivered successfully.

JAXM also allows for the use of profiles, which make it easy to create specialized SOAP messages such as SOAP-RP or ebXML messages.


Resources

About the author

Photo of Nicholas Chase

Nicholas Chase, a Studio B author, has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, and an Oracle instructor. More recently, he was the Chief Technology Officer of Site Dynamics Interactive Communications in Clearwater, Florida, USA, and is the author of four books on Web development, including XML Primer Plus (Sams). He loves to hear from readers and can be reached at nicholas@nicholaschase.com.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, SOA and Web services
ArticleID=11656
ArticleTitle=Tip: Send and receive SOAP messages with SAAJ
publish-date=01222008
author1-email=nicholas@nicholaschase.com
author1-email-cc=dwxed@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers