Java Development News:

EJB 2.1 Web Services: Part 2: Monson-Haefel's Guide to Enterprise JavaBeans

By Richard Monson-Haefel

01 Sep 2002 | TheServerSide.com

Introduction

Richard Monson-Haefel is the author of Enterprise JavaBeans, 3rd Edition, Java Message Service and one of the world's leading experts on Enterprise Java. He is co-founder of OpenEJB, an open source EJB container used in Apple Computer's WebObjects, and an independent consultant.

When I first planned this two-part installment I decided to cover JAX-RPC in the first part (and did), and SAAJ and JAXM in the second part. As it turns out, though, JAXM is not destined to become a part of J2EE and thus will not become an API that EJB developers can depend on. The JAXM message-driven bean I mentioned in previous installments seems more like a pipe dream than a reality. Indeed, JAXM itself looks like an API that was in decline before it ever got started.

One result is that this article is shorter than usual. The section on SAAJ provides a quick overview and an example of its use. The JAXM section focuses on why JAXM didn't become a part of J2EE. There seemed little reason at this point to show JAXM examples or go into detail about the JAXM message-driven bean.

The book I'm currently working on for Addison-Wesley, J2EE Web Services, goes into great detail about using the SAAJ API and the Java Activation Framework on which it depends. It also provides coverage of how SAAJ is used with JAX-RPC (Java API for XML-RPC), JavaMail, JMS (Java Message Service), and JAXM (Java API for XML Messaging). To cover SAAJ thoroughly would take about 20,000 words. That seemed a bit much for an article, so I opted for a concise overview that should give you a better understanding of SAAJ's usefulness.


SAAJ

The SOAP with Attachments API for Java (SAAJ) is an API-based SOAP toolkit that models the structure of SOAP messages. To be precise, SAAJ models SOAP Messages with Attachments (SwA), the MIME message format for SOAP. The SwA specification is actually a note maintained by the World Wide Web Consortium (W3C)1 . W3C uses "note" to distinguish suggestions and works in progress from official recommendations. Nevertheless, for all intents and purposes SwA is a standard used throughout the Web services industry.

Java developers can use SAAJ (pronounced to rhyme with page) to create, read, or modify SOAP messages. The API includes classes and interfaces that model SOAP elements (Envelope, Body, Header, Fault, etc.), XML namespaces, attributes, text nodes, and MIME attachments. You can use SAAJ to manipulate simple SOAP messages (just the XML, without any attachments) or more complex SOAP messages, with MIME attachments. SAAJ can be used in combination with JAX-RPC, which is the J2EE standard API for sending and receiving SOAP messages, to represent literal XML document fragments. You can also use SAAJ independently of JAX-RPC; it has its own, optional facilities for basic messaging using request-reply style messaging with the HTTP 1.1 binding.

SAAJ is based on the Abstract Factory pattern2. SAAJ is an abstract family of types, where each type of object is manufactured by another type in the SAAJ family. In the SAAJ implementation of Abstract Factory, the MessageFactory class is the root. It's responsible for manufacturing an instance of itself, which can in turn be used to manufacture a SOAPMessage. A SOAPMessage contains a SOAPPart that represents the SOAP document, and zero or more AttachmentPart objects that represent attachments (GIFs, PDFs, etc.) The SOAPPart contains a SOAPEnvelope, a SOAPBody, a SOAPHeader, and other types of objects. Figure 1 shows two class diagrams: (A) shows the relationship among types in SAAJ and (B) is an inheritance diagram for the SAAJ interfaces which model the SOAP document.




Figure 1 - SAAJ Class Hierarchy


You may have noticed that portions of the SAAJ API, especially the SOAPElement type, duplicates semantics already defined by the W3C's DOM (Document Object Model). Apparently, the expert group that created SAAJ decided not to use DOM because they felt that it provided inadequate support for XML Namespaces, which is an important part of SOAP messaging

An alternative to creating complete SOAPMessage objects using the MessageFactory, the SOAPFactory class can be used to create XML document fragments. This is the factory that is typically employed when using SAAJ with JAX-RPC.

The best way to learn SAAJ is to jump right in, and use it to build a simple SOAP message like this one written in straight XML:


<?xml version='1.0' ?>
<env:Envelope
 xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'
 xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
 xmlns:titan='http://www.jwsbook.org/1ed/BookPrice'
 encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
   <Body>
      <titan:getBookPrice>
          <isbn xsi:type='string'>1565928695
      </titan:getBookPrice>
   </Body>
</env:Envelope>

The Example_1 Java application uses SAAJ to create a message that's semantically equivalent to the one just listed:


import javax.xml.soap.*;

public class Example_1 {
   public static void main(String [] args) throws SOAPException{

        MessageFactory msgFactory = MessageFactory.newInstance();
        SOAPMessage message = msgFactory.createMessage();
        SOAPPart soap = message.getSOAPPart();
        SOAPEnvelope envelope = soap.getEnvelope();
        envelope.getHeader().detachNode();
        SOAPBody body = envelope.getBody();
        SOAPElement getBookPrice = body.addChildElement(
                                 "getBookPrice","titan",
                                 "http://www.jwsbook.org/1ed/BookPrice");
        getBookPrice.setEncodingStyle(
                            SOAPConstants.URI_NS_SOAP_ENCODING);
        SOAPElement isbn = getBookPrice.addChildElement("isbn");
        isbn.addNamespaceDeclaration("xsi",
                            "http://www.w3.org/2001/XMLSchema-instance");
        Name xsiType = envelope.createName("type","xsi",
                            "http://www.w3.org/2001/XMLSchema-instance");
        isbn.addAttribute(xsiType,"string");
        isbn.addTextNode("1565928695");

        message.writeTo(System.out);
    }
}

If you examine the above example, you'll see that SAAJ models the exact structure of the SwA message format. Figure 2 shows the one-for-one correlation between the elements in the SOAP message and the SAAJ types used to model those elements.




Figure 2 - Comparing a SAAJ instance to a SOAP document


Of course the above example is quite simple. It doesn't include any attachments, which can get fairly complicated. Attachments in SwA are frequently binary files or other non-XML type files, which are referenced by the SOAP document. SAAJ relies on the Java Activation Framework (JAF) to add attachments and handle the conversion of objects into data streams and vice versa. The following code snippet uses SAAJ to attach a PDF document to a SOAP message.


    MessageFactory msgFactory = MessageFactory.newInstance();
    SOAPMessage message = msgFactory.createMessage();
    AttachmentPart pdfAttach = message.createAttachmentPart();
    FileDataSource file = new FileDataSource("manuscript.pdf");
    DataHandler pdfDH = new DataHandler(file);
    pdfAttach.setDataHandler(pdfDH);

To work with attachments successfully you must understand JAF. JAF is an excellent framework for handling MIME data, but it has its limitations, most of them associated with the use of DataContentHandler types. The specifics behind JAF's limitations are far too involved to cover in this article, but you can circumvent most of them by using the JAF DataSource types like the javax.activation.FileDataSource type employed in the preceding example.

SAAJ is a very useful API that enables you to construct SwA messages in just about any application. In some cases you'll use SAAJ with JAX-RPC for literal style messaging and SOAP message handlers but you can also use SAAJ in conjunction with other APIs like JavaMail, JMS, and JAXM. Once a Java application has constructed an SwA message, it can also use SAAJ to convert the message into a binary stream, which it then can exchange with a Web service using any number of APIs.


JAXM

In a previous article for this column I mentioned that I planned to provide extensive coverage of JAXM, but I've since concluded that its future as a Web services API is questionable.

JAXM was originally slated to become part of J2EE, but lost vendor support when it became obvious that there was too much overlap between JAXM and other messaging APIs. J2EE vendors objected to JAXM primarily because its functionality can be duplicated in JMS and JAX-RPC. They considered "yet another messaging API" to be an unnecessary burden on the J2EE developer community. Although the JCP (narrowly) approved JAXM as an API, the most powerful J2EE vendors (IBM and BEA) rejected the specification, which which may have torpedoed its chance to become a part of the J2EE platform. However, Sun Microsystems tells a different story. They maintain that JAXM wasn't included in J2EE because there is not, as yet, enough demand for a store-and-forward SOAP messaging API. That eventually demand will increase and JAXM will be included in the suite of J2EE APIs.

Some smaller vendors specializing in non-J2EE Web service integration platforms do implement JAXM, among them IONA's XMLBus and Systinet's WASP products. It's possible other non-J2EE vendors will also adopt JAXM. Because it can be used as a J2EE Connector API, you may be able to use a third-party JAXM provider along with your J2EE platform. This combination might be advantageous if the JAXM vendor provides a particularly useful EAI or B2B integration suite.

The future of JAXM is uncertain at best. Without support from major J2EE vendors it's hard to imagine it will thrive in the years to come. Some believe that it's an excellent standard API for non-J2EE vendors, while others maintain that it will eventually be allowed back into the J2EE fold. I believe the latter will never happen; and that support by non-J2EE vendors is JAXM's only hope for survival.

That JAXM did not become part of the J2EE platform is a surprise, but in retrospect not a disapointment. Vendors are right to shy away from an API whose funtionality is largly duplicated by other technologies. You should temper your own enthusiasm for JAXM with reflection on the realities of the marketplace: If you build key parts of your system on an API that fails to win vendor support, they probably will not be portable. Of course, portability is not always as important as interoperability, and a JAXM provider may be the best choice for interoperating easily and seamlessly with certain platforms (e.g., ebXML or GXA).


Wrapping Up

The primary focus behind Enterprise JavaBeans support for Web services is JAX-RPC, which is essentially Java RMI over SOAP. SAAJ is a big part of the suite of EJB Web services offerings because it enables you to build object-oriented representations of SOAP messages, including attachments. SAAJ is an integral part of JAX-RPC but can also be used with other APIs like JavaMail, JMS, and JAXM. JAXM, however, you should hold suspect for the time being. While it can be an excellent integration API for non-J2EE vendors, it's not a J2EE API and, in general, isn't very portable.

Next month's article will cover the new Timer Service in EJB 2.1, which allows entity and other types of beans to receive schedule events.


Notes

  1. Microsoft and Hewlett-Packard submitted the W3C note regarding SwA to W3C by in December 2000.

  2. Erich Gamma, et. l. Design Patterns, Elements of Reusable Object-Oriented Software, Addison-Wesley (1995), page 87.



copyright notice (c) Copyright 2002 Richard Monson-Haefel. All rights reserved.

Related Content

Related Resources