SAAJ 1.2 and DOM 2



SAAJ 1.2 and DOM 2

SAAJ 1.1, the first official version of SAAJ, was not as flexible as it could have been. Vendors and developers complained that it should have been based on DOM 2. They claimed—rightly—that a DOM-based SAAJ would be a more flexible API, would make it easier to work with arbitrary XML document fragments, and would allow SAAJ to work well with DOM. In recognition of version 1.1's shortcomings, SAAJ 1.2 redefines the API so that it's an extension of the DOM 2 Java object model. SAAJ is now a lot more powerful, because you can use it to create and manipulate SOAP messages, but you can also take advantage of low-level DOM 2 functionality as the need arises. In addition, you can import Nodes from a DOM 2 document into a SOAP message, which is useful when working with JAX-RPC message handlers and Document/Literal payloads.

This section assumes you are already familiar with DOM 2. If you're not, then you should take time out to read Chapter 21: DOM 2 now, or this section is not going to make much sense to you. Chapter 21 will teach some of the basics about the DOM 2 programming API and how it's used. To find out where you can learn still more about DOM, see the introduction to Part VI: JAXP.

Aligning SAAJ 1.2 with DOM 2 didn't really complicate the SAAJ API too much. In most cases interfaces were simply redefined to extend DOM 2 interface types like Document, Element, and Text. Figure shows how SAAJ 1.2 types inherit from DOM 2 types.

SAAJ 1.2 and DOM 2 Inheritance Diagram (DOM types are in gray, SAAJ types in black.)

graphics/13fig05.jpg

SaajExample_9 in Listing 13-29 is a simple example of how you can use SAAJ 1.2 and DOM 2 in concert to construct a Document/Literal SOAP message.

Listing 13-29 Importing a DOM Element into a SAAJ 1.2 SOAPMessage
package com.jwsbook.saaj;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import javax.xml.soap.*;

public class SaajExample_9 {
  public static void main(String [] args) throws Exception{

    // Read an XML document from a file into a DOM tree using JAXP.
    String filePath = args[0];
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder parser = factory.newDocumentBuilder();
    Document xmlDoc = parser.parse(filePath);

    // Create a SAAJ SOAPMessage object. Get the SOAPBody and SOAPPart.
    MessageFactory msgFactory = MessageFactory.newInstance();
    SOAPMessage message = msgFactory.createMessage();
    SOAPPart soapPart = message.getSOAPPart();
    SOAPBody soapBody = soapPart.getEnvelope().getBody();

    // Import the root element and append it to the body of the SOAP message.
    Node elementCopy =
      soapPart.importNode(xmlDoc.getDocumentElement(), true);
    soapBody.appendChild(elementCopy);

    // Output SOAP message.
    SaajOutputter.writeToScreen(message);
  }
}

SaajExample_9 reads an XML document from a file and has a DOM provider parse it into a Document object. It also creates a new SOAPMessage object. The application imports the root of the XML document into the SOAPPart (using the Document.importNode() method) and subsequently appends the imported copy to the SOAPBody (using the Node.appendNode() method).

As an alternative to using the importNode() method, you can use the SOAP Body.addDocument() method, which requires a lot less code, but has a significant side effect. When you call SOAPBody.addDocument(), the root element of the Document is actually moved (not copied) to become a child of the SOAPBody. In other words, the root element is physically reassigned to the SOAPMessage object. As you learned earlier in chapter 21, a Node cannot refer to more than one Document object, so moving the root element to the SOAPMessage (specifically to the SOAPPart) invalidates the source Document—there is no longer a root element that refers to it. In Listing 13-30, SaajExample_10 shows how you can use SOAPBody.addDocument().

Listing 13-30 Moving a DOM Root Element to a SAAJ 1.2 SOAPMessage
package com.jwsbook.saaj;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.soap.*;

public class SaajExample_10 {
  public static void main(String [] args) throws Exception{

    // Read an XML document from a file into a DOM tree using JAXP.
    String filePath = args[0];
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder parser = factory.newDocumentBuilder();
    Document xmlDoc = parser.parse(filePath);

    // Create a SAAJ SOAPMessage object. Get the SOAPBody.
    MessageFactory msgFactory = MessageFactory.newInstance();
    SOAPMessage message = msgFactory.createMessage();
    SOAPBody soapBody = message.getSOAPPart().getEnvelope().getBody();

    // Append the root element of the XML doc to the body of the SOAP message.
    soapBody.addDocument(xmlDoc);

    // Output SOAP message.
    jwsed1.SaajOutputter.writeToScreen(message);
  }
}