1.6. Send or Post a SOAP message using SAAJ (document/literal)

A more structural way to construct and to post a SOAP message to a web service can be accomplished by the use of SAAJ.

1.6.1. Construct dynamically your SOAP message

By using SAAJ your can dynamically construct your SOAP request. So it is possible, at runtime, to detect for example the operation style of the web service (by accessing the WSDL) and modify the namespace you will use in function of this type: document/literal -> body namespace (typically http://something/types or uri:something/types) or rpc/encoded -> type namespace (same but /wsdl).

The following example construct dynamically the SOAP message before to post it to the web service. The program simply echo the SOAP response returned by the service. You can parse the response using DOM or SAX to extract the values you need.

Example 1-12. Build and post a SOAP message using SAAJ

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;
import javax.xml.soap.SOAPElement;
// add this import if you need soapaction
//import javax.xml.soap.MimeHeaders;

import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.Source;

import javax.xml.transform.stream.StreamResult;

public class Client {

  public static void main(String[] args) {

    try {
	// Create the connection
	SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance();
	SOAPConnection conn = scf.createConnection();
			
	// Create message
	MessageFactory mf = MessageFactory.newInstance();
	SOAPMessage msg = mf.createMessage();

        // Add eventually a SoapAction header if necessary
        /*
        MimeHeaders hd = msg.getMimeHeaders();
        hd.addHeader("SOAPAction", "urn:yoursoapaction");
        */

	// Object for message parts
	SOAPPart sp = msg.getSOAPPart();

	SOAPEnvelope env = sp.getEnvelope();
	env.addNamespaceDeclaration("xsd","http://www.w3.org/2001/XMLSchema");
	env.addNamespaceDeclaration("xsi","http://www.w3.org/2001/XMLSchema-instance");
	env.addNamespaceDeclaration("enc","http://schemas.xmlsoap.org/soap/encoding/");
	env.addNamespaceDeclaration("env","http://schemas.xmlsoap.org/soap/envelop/");
	env.setEncodingStyle("http://schemas.xmlsoap.org/soap/encoding/");

	SOAPBody bd = env.getBody();

        // Populate body
	// Main element and namespace
	SOAPElement be = bd.addChildElement(env.createName("readLS",
		"ans1",
		"http://phonedirlux.homeip.net/types")); 
        // namespace to use for my rpc/encoded wsdl version is:
        // http://phonedirlux.homeip.net/wsdl
        // note, in this case the endpoint address is /rcx-ws-rpc/rcx

	// Add content
	be.addChildElement("String_1").addTextNode("your message or e-mail").setAttribute("xsi:type","xsd:string");

	// Save message
	msg.saveChanges();

	// View input
	System.out.println("\n Soap request:\n");
	msg.writeTo(System.out);
	System.out.println();

	// Send
	String urlval = "http://www.pascalbotte.be/rcx-ws/rcx";
        // or /rcx-ws-rpc/rcx for my rpc/encoded web service

	SOAPMessage rp = conn.call(msg, urlval);

	// View the output
	System.out.println("\nXML response\n");

	// Create transformer
	TransformerFactory tff = TransformerFactory.newInstance();
	Transformer tf = tff.newTransformer();

	// Get reply content
	Source sc = rp.getSOAPPart().getContent();

	// Set output transformation
	StreamResult result = new StreamResult(System.out);
	tf.transform(sc, result);
	System.out.println();
			
	// Close connection
	conn.close();

      }
      catch (Exception e){
	System.out.println(e.getMessage());
      }
    }
  }

Be on a hurry? or just for debugging, you can send a text file containing the SOAP message with SAAJ. See the next section.

1.6.2. Post a prepared SOAP message with SAAJ

No more dynamic construction of the SOAP message this time, let's use a simple text editor and type the soap message we want to send.

Now the code will be shorter and you can easily use it for testing purpose.

Example 1-14. Post a SOAP message in a text file, to a web service using SAAJ

  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 java.io.FileInputStream;
  import javax.xml.transform.stream.StreamSource;

  import javax.xml.transform.TransformerFactory;
  import javax.xml.transform.Transformer;
  import javax.xml.transform.Source;

  import javax.xml.transform.stream.StreamResult;

  public class Client {

    public static void main(String[] args) {

      try {
	// Create the connection
	SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance();
	SOAPConnection conn = scf.createConnection();
			
	// Create message
	MessageFactory mf = MessageFactory.newInstance();
	SOAPMessage msg = mf.createMessage();
			
	// Object for message parts
	SOAPPart sp = msg.getSOAPPart();
	StreamSource prepMsg = new StreamSource(
	  new FileInputStream("path/prepared.msg"));
	sp.setContent(prepMsg);
			
	// Save message
	msg.saveChanges();
			
	// View input
	System.out.println("\n Soap request:\n");
	msg.writeTo(System.out);
	System.out.println();
			
	// Send
	String urlval = "http://www.pascalbotte.be/rcx-ws/rcx";
	SOAPMessage rp = conn.call(msg, urlval);
			
	// View the output
	System.out.println("\nXML response\n");
			
	// Create transformer
	TransformerFactory tff = TransformerFactory.newInstance();
	Transformer tf = tff.newTransformer();
			
	// Get reply content
	Source sc = rp.getSOAPPart().getContent();
			
	// Set output transformation
	StreamResult result = new StreamResult(System.out);
	tf.transform(sc, result);
	System.out.println();
			
	// Close connection
	conn.close();
			
      }
      catch (Exception e) {
	System.out.println(e.getMessage());
      }
    }
  }

Using this method, you can send a soap message using SAAJ with only 10 lines of code!