Creating SOAP Messages Programmatically

In this tutorial we will learn how to create a javax.xml.soap.SOAPMessage programmatically using SOAPBody and SOAPElement objects and how to create one from a String. First of all the javax.xml.soap.SOAPMessage is the root class for all SOAP messages. As transmitted on the "wire", a SOAP message is an XML document or a MIME message whose first body part is an XML/SOAP document.
A SOAPMessage object consists of a SOAP part and optionally one or more attachment parts. The SOAP part for a SOAPMessage object is a SOAPPart object, which contains information used for message routing and identification, and which can contain application-specific content. All data in the SOAP Part of a message must be in XML format.  The following code shows how you can code a SOAP Request:

private SOAPMessage createSOAPRequest() throws Exception
{
        MessageFactory messageFactory = MessageFactory.newInstance();
        SOAPMessage soapMessage = messageFactory.createMessage();
        SOAPPart soapPart = soapMessage.getSOAPPart();

        // SOAP Envelope
        SOAPEnvelope envelope = soapPart.getEnvelope();
        envelope.addNamespaceDeclaration("acme", "http://samples.saaj.jms");

        // SOAP Body
        SOAPBody soapBody = envelope.getBody();
        SOAPElement soapBodyElem = soapBody.addChildElement("employee", "acme");
        SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("id", "acme");
        soapBodyElem1.addTextNode("10");

        soapMessage.saveChanges();

        System.out.println("Request SOAP Message = ");
        soapMessage.writeTo(System.out);
        System.out.println();
        return soapMessage;
}

This is the SOAPMesage XML that will be created:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:acme="http://samples.saaj.jms">
   <SOAP-ENV:Header />
   <SOAP-ENV:Body>
      <acme:employee>
         <acme:id>10</acme:id>
      </acme:employee>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The following code, shows how to parse into a String the soapMessage object:

ByteArrayOutputStream outstream = new ByteArrayOutputStream();
soapMessage.writeTo(outstream);
String strMsg = new String(outstream.toByteArray());

Create a SOAPMessage from an XML String

Another strategy for creating a SOAPMessage implies using a SAXParser to create the SOAP Message from an XML String:

package org.example;

import java.io.IOException;
import java.io.StringReader;
import java.util.Iterator;
import javax.xml.parsers.*;
import javax.xml.soap.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class CreateSOAPfromXML {

public static SOAPElement createSOAPElementFromXMLString(String xmlString)
       throws ParserConfigurationException, IOException, SAXException
   {
       StringReader stringReader = new StringReader(xmlString);
       InputSource inputSource = new InputSource(stringReader);
       SAXParserFactory factory = SAXParserFactory.newInstance();
       factory.setNamespaceAware(true);
       SAXParser parser = factory.newSAXParser();
       SoapElementSaxHandler handler = new SoapElementSaxHandler();
       parser.parse(inputSource, handler);
       return handler.getSOAPElement();
   }

}

And here is the SoapElementHandler required for this class:

package org.example;

import java.util.ArrayList;
import java.util.HashMap;
import javax.xml.soap.*;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SoapElementHandler extends DefaultHandler {
	private HashMap prefixURIMapping;
	private ArrayList uris;
	private SOAPElement rootElement;
	private SOAPElement currentElement;
	private SOAPFactory soapFactory;

	public SoapElementHandler() {
		prefixURIMapping = new HashMap();
		uris = new ArrayList();
		rootElement = null;
		currentElement = null;
	}

	public SOAPElement getSOAPElement() {
		return rootElement;
	}

	public void startDocument() throws SAXException {
		try {
			soapFactory = SOAPFactory.newInstance();
		} catch (SOAPException e) {
			throw new SAXException("Error: Can't create a SOAPFactory instance", e);
		}
	}

	public void startPrefixMapping(String prefix, String uri) {
		prefixURIMapping.put(uri, prefix);
		uris.add(uri);
	}

	public void characters(char ch[], int start, int length) throws SAXException {
		String str = String.valueOf(ch);
		if (length > 0)
			try {
				currentElement.addTextNode(str.substring(start, start + length));
			} catch (SOAPException e) {
				throw new SAXException("Error: Can't add a text node into SOAPElement from text", e);
			}
	}

	public void endElement(String uri, String localName, String qName) {
		if (currentElement != rootElement)
			currentElement = currentElement.getParentElement();
	}

	public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
		String prefix = (String) prefixURIMapping.get(namespaceURI);
		try {
			if (rootElement == null && currentElement == null) {
				rootElement = soapFactory.createElement(localName, prefix, namespaceURI);
				currentElement = rootElement;
			} else {
				currentElement = currentElement.addChildElement(localName, prefix, namespaceURI);
			}
			if (uris.size() > 0) {
				for (int i = 0; i < uris.size(); i++) {
					String uri = (String) uris.get(i);
					String pre = (String) prefixURIMapping.get(uri);
					currentElement.addNamespaceDeclaration(pre, uri);
				}

				uris.clear();
			}
			for (int i = 0; i < atts.getLength(); i++) {
				javax.xml.soap.Name attriName;
				if (atts.getURI(i) != null) {
					String attriPre = (String) prefixURIMapping.get(atts.getURI(i));
					attriName = soapFactory.createName(atts.getLocalName(i), attriPre, atts.getURI(i));
				} else {
					attriName = soapFactory.createName(atts.getLocalName(i));
				}
				currentElement.addAttribute(attriName, atts.getValue(i));
			}

		} catch (SOAPException e) {
			throw new SAXException(e);
		}
	}

}

Related articles available on mastertheboss.com

JBoss web services

JAX-WS simplifies the development model for a web service endpoin

What is a Web Service One Way invocation?

JBoss recipe of the day

Asynchronous web services with JBoss WS

Developing rigorous and responsive web service client application

How to change the default Web Service deployment Port ?

JBoss recipe of the day

Using Axis Web Services with JBoss

Still not ready for JBoss WS ? if you don't have a JDK 1.5 compli

Invoking JBoss Web Services with Flex

Flex® is a free, open source framework for building highly in

Follow us on Twitter