Archive for Web Services

The Sorry State of SAAJ

When I started working on Spring Web Services some three years ago, I needed a way to represent a SOAP message. I was a good boy and used J2EE, or more specifically: the SOAP with Attachments API for Java™, also know as SAAJ, also known as the package javax.xml.soap. Founding Spring-WS on a specification seemed like the Proper Thing To Do, and gave me a warm fuzzy feeling inside.

Over time, I found out that SAAJ is quite possibly the worst implemented piece of J2EE Java EE out there. Now I’m sharing the pain with you in this post because, well, sharing is the first step in acceptance.

A Bit Of History

SAAJ started out as being part of the Java™ API for XML Messaging (JAXM). JAXM actually was quite nice: none of this “look ma, it’s just a method call!” nonsense that JAX-RPC offered. Unfortunately, JAXM was pulled in favor of JAX-RPC. Some of JAXM survived, namely the representation of a SOAP message, and was rebranded SAAJ 1.1.

SAAJ 1.1 basically offered a DOM-like representation of a SOAP message: SOAPEnvelope has a SOAPBody, and an optional SOAPHeader, and so on. All elements extended SOAPElement, which in turn extended Node. javax.xml.soap.Node, that is, not org.w3c.dom.Node, which - coincidentally - was the main problem with SAAJ 1.1: there was no easy way to integrate SAAJ with existing JAXP code. Even though SAAJ was similar to org.w3c.dom, there was no clear conversion path, besides writing the whole message to a buffer and reading that with JAXP. Yay.

The wise folks at the JCP decided to change that in SAAJ 1.2: in this version, all SAAJ classes extend their W3C DOM counterparts. So javax.xml.soap.Node extends org.w3c.dom.Node, SOAPElement extends Element, and so on, and so forth. Not everybody thought this was a clever idea; clearly Hani was not among those in favor. At this point, SAAJ was added to J2EE 1.4. Some J2EE vendors seem to agree with Hani as to whether this was a good idea, more about that later.

SAAJ 1.3 introduced some more stuff: support for SOAP 1.2, MTOM, and more. As a result of this plethora of features, SAAJ graduated from Java EE to Java SE in version 6. I think this was probably more a side-effect of SUN putting JAX-WS in Java 6, which is subject to a different rant altogether (short rant preview: had I implemented JAX-WS, I would be pretty pissed at SUN. Aren’t there laws against this sort of bundling?)

The SAAJ Saga continues

So, as of SAAJ 1.2, a SOAPElement isa W3C DOM Element. This makes sense, because now you can use JAXP to put XML content into the some message. For instance, you can use standard XML-DSIG or XML-ENC libraries to sign or decrypt a SOAP message, handy when doing WS-Security. Or, you can read a bit of XML from a file, and dump that into the SOAP body as a payload. The only caveat mentioned in the javax.xml.soap javadoc is that:

an application that starts to use SAAJ APIs on a tree after manipulating it using DOM APIs must assume that the tree has been translated into an all SAAJ tree and that any references to objects within the tree that were obtained using DOM APIs are no longer valid.

No problem, we can do that. Just don’t keep any references dangling around. So we might write something like:

MessageFactory messageFactory = MessageFactory.newInstance();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
SOAPMessage message = messageFactory.createMessage();
Document document = createDocument();
SOAPBody body = message.getSOAPBody();
transformer.transform(new DOMSource(document), new DOMResult(body));
body = message.getSOAPBody();
transformer.transform(new DOMSource(body), new StreamResult(System.out));
message.writeTo(System.out);

Here, we create a new SAAJ message using the MessageFactory. Next, we create a W3C DOM document, and we use a javax.xml.transform.Transformer to transform the document to the SOAP body. As a result the root element of the document should be appended to the SOAP body, it will become the payload of the message. Next, we write the body to the console, and finally we write the whole message to the console. Simple enough, and conforming to the spec.

Yet, this simple program does not work on the majority of Java EE servers.

The Acid Test

I created a simple Servlet which basically does the above, and ran it in a wide variety of Java EE application servers. Here is an overview, all J2EE 1.4 or higher (with the exception of Tomcat, of course, I used that as a baseline and to test the Axis 1 SAAJ implementation). I’ve listed the name, the MessageFactory implementation provided by the server, the test result, and the exception given - if any. Finally, I’ve submitted bugs where possible, because I am a Good Citizen.

Application Server MessageFactory Result Exception Bug
Geronimo 2.1.2 with Jetty org.apache.geronimo.webservices.saaj.GeronimoMessageFactory
Geronimo 2.0.2 with Tomcat org.apache.geronimo.webservices.saaj.GeronimoMessageFactory TransformerException when transforming Document to SOAPBody GERONIMO-4029
AXIS2-3808
GlassFish v2ur1 com.sun.xml.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl
JBoss 4.2.2 org.jboss.ws.core.soap.MessageFactoryImpl IndexOutOfBoundsException when transforming SOAPBody to stream JBWS-2186
OC4J 10.1.3.1 oracle.j2ee.ws.saaj.soap.MessageFactoryImpl TransformerException when transforming Document to SOAPBody
Tomcat 6.0.16 with SAAJ RI com.sun.xml.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl
Tomcat 6.0.16 with Axis 1.4 SAAJ org.apache.axis.soap.MessageFactoryImpl
WebLogic 9.2 weblogic.webservice.core.soap.MessageFactoryImpl UnsupportedOperationException when getting SOAPBody
WebLogic 10.0 weblogic.webservice.core.soap.MessageFactoryImpl UnsupportedOperationException when getting SOAPBody
WebSphere 6.1 com.ibm.ws.webservices.engine.soap.MessageFactoryImpl

Of this bunch, WebLogic is the clear winner. Every time you call SOAPMessage.getBody(), WebLogic barfs up a UnsupportedOperationException, saying that “This class does not support SAAJ 1.1″! The thing is: it supports SAAJ 1.1 just fine, it just doesn’t do SAAJ 1.2. You know, J2EE 1.4 and all that.

You Can Help!

Obviously, I am missing WebSphere in this overview. Because I run OS X, I can’t install WebSphere. So if you want to be a Good Citizen too, you can run my little test program on WebSphere, or any other app server I have missed. Update: craig has given me the info for WebSphere, and I’ve updated the table accordingly. Thanks! I’m still interested in any other J2EE 1.4+ app servers I’ve missed, though.

Or if you don’t trust me, you can test it yourself. Just deploy the WAR, and let me know in a comment below.

saaj-test.war

If you don’t trust me at all, you can get the sources. It has a build.xml and all:

saaj-test.zip

Let’s hope that this post solves the issues with SAAJ, because I Want To Believe.

Comments (8)

REST FAQ

Apparently, the REST FAQ is hosted at:

http://rest.blueoxen.net/cgi-bin/wiki.pl?RestFaq

Quite a RESTful URI! ;)

Comments (7)

Platonic REST

Once, in an ancient past, I studied philosophy for a couple of years. At the time, I could not really appreciate the subject, so I quit and switched to Artificial Intelligence. In retrospect, I think I might have been too young to appreciate it fully. Having a bit more experience in life sure helps.

That said, I don’t think it was a waste of time. I learned a great deal about logic, proper argumentation, and of course the history of philosophy. The latter might seem impractical, but it sometimes does apply, even in the field I’m currently working in.

Plato

Take Plato, for instance. Together with Socrates and Aristotle, he is one of the founders of Western culture. Famous for writing up the Socrates dialogues, he also wrote some works of his own, one of which is The Republic. In this work, he describes his famous Allegory of the Cave, which goes something like this:

Imagine prisoners, who have been chained since their childhood deep inside a cave: not only are their limbs immobilized by the chains; their heads are chained in one direction as well so that their gaze is fixed on a wall.

Behind the prisoners is an enormous fire, and between the fire and the prisoners is a raised walkway, along which puppets of various animals, plants, and other things are moved along. The puppets cast shadows on the wall, and the prisoners watch these shadows. When one of the puppet-carriers speaks, an echo against the wall causes the prisoners to believe that the words come from the shadows.

The prisoners engage in what appears to us to be a game: naming the shapes as they come by. This, however, is the only reality that they know, even though they are seeing merely shadows of objects. They are thus conditioned to judge the quality of one another by their skill in quickly naming the shapes and dislike those who play poorly.

There are many interpretations of this allegory, but for me it has always been about not knowing the true reality of things; we only see shadows cast on the cave wall.

REST

Fast-forward a couple of thousand years, and let’s look at REST, the key design principles of which are:

  • Identifiable Resources
  • Uniform interface
  • Resource representations
  • Stateless conversation
  • Hypermedia

Resources are identified by a unique identifier (a URI), and you interact with the resources through a uniform interface with well-defined operations (i.e. GET, POST, etc.). Using these operations, you create representations of resources (such as a text/html representation, or application/xml). Typically, these representations contain links, making up hypermedia.

What does this have to do with Plato? Well, in REST there is no one true representation of a resource. There can be many of them, each of which is as important as the other. In other words, the representation is just a shadow of the resource, cast of the cave wall…

Comments (1)

A Fluent Interface for XML DOM APIs

The concept of fluent interfaces is certainly not new to me, but recently I’ve had the chance to bring it into practice by using EasyMock 2. EasyMock 2 uses the features of Java 5 to greatly simplify the programming model for mock objects.

This got me thinking about XML, and DOM in particular. Let’s say we want to create the following piece of XML using DOM:

<contacts>
   <contact>
      <name>John Doe</name>
      <phone type="home">555-12345</phone>
      <phone type="work">555-67890</phone>
   </contact>
</contacts>
 Basically, the way to create this XML using the standard DOM API look something like:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.newDocument();
Element name = doc.createElement("name");
name.setTextContent("John Doe");
Element phone1 = doc.createElement("phone");
phone1.setAttribute("type", "home");
phone1.setTextContent("555-12345");
Element phone2 = doc.createElement("phone");
phone2.setAttribute("type", "work");
phone2.setTextContent("555-67890");
Element contact = doc.createElement("contact");
contact.appendChild(name);
contact.appendChild(phone1);
contact.appendChild(phone2);
Element contacts = doc.createElement("contacts");
contacts.appendChild(contact);
doc.appendChild(contacts);

Not really fluent in any way, and quite verbose as well.Things improve somewhat with JDOM, because it uses concrete classes rather than interfaces, so we don’t need the Document factory. Also, most methods conveniently return this, so you can chain them:

Document doc = new Document();
Element name = new Element("name").setText("John Doe");
Element phone1 = new Element("phone").setAttribute("type", "home").setText("555-12345");
Element phone2 = new Element("phone").setAttribute("type", "work").setText("555-67890");
Element contact = new Element("contact").addContent(name).addContent(phone1).addContent(phone2);
Element contacts = new Element("contacts").addContent(contact);
doc.addContent(contacts);

This is certainly less verbose, but is it fluent? Those two concepts don’t necessarily mean the same thing. An API can be very succinct, but that does not necessarily mean it is fluent. Quoting Martin Fowler: The [fluent] API is primarily designed to be readable and to flow. The example above doesn’t flow; the approach is quite linear, even though we are creating a hierarchal tree.

Compare this to the API of XLinq, the XML component of Microsoft’s LINQ effort1:

XElement contacts = 
   new XElement("contacts", 
      new XElement("contact", 
         new XElement("name", "John Doe"), 
         new XElement("phone", "555-12345",  
            new XAttribute("type", "home")), 
         new XElement("phone", "555-67890", 
            new XAttribute("type", "work"))
        )
      ); 

Note that by indenting (and squinting a bit) the code to construct the XML tree shows the structure of the underlying XML. And this is due to the way the API was designed: clever use of .NET operator overloading, variable constructor arguments, and generics allow for this.

I really miss something like this in the Java space. So much, in fact, that I’m thinking about writing one myself. We don’t have operator overloading in Java, but we do have static imports. So that could mean we could end up with something along the lines of:

import static org.easydom.EasyDom.*;

Element contacts =
   element(name("contacts"),
      element(name("contact"),
         element(name("name"), "John Doe"),
         element(name("phone"), "555-1234",
            attribute(name("type"), "home")),
         element(name("phone"), "555-567890",
            attribute(name("type"), "work"))
         )
      );

The idea is that the EasyDom object contains nothing but static methods, just like EasyMock does. The name() method, for instance, returns a QName, necessary to construct an element using element(), or an attribute using attribute(). I’m not sure about the name() requirement, dropping that would make it more consice. So far, so good.

There are two things stopping me from creating this EasyDom API:

  1. Does the world really need another DOM API? I thought about returning or wrapping W3C DOM, but that would mean that only the DOM creation API is fluent, and the end result still has weird behavior like using NodeList where a List<Element> would be nicer.
  2. Creating a DOM API is hard. Creating a fluent interface is even harder. I’ve got enough work already.
Leave a comment to change my mind :) .

Update 20070514: Guillaume is right when he says that the Groovy Markup builder has a fluent interface. And on that note, Tareq Abed Rabbo has written a nice post about combining Groovy with Spring-WS.


1 - If you don’t know anything about LINQ, read this. I wish we had something similar in the Java space.

Comments (6)

WS-* does not imply strict typing

Stefan Tilkov writes: afc156de34ba6e12746f6501c63e6ba3

Just like Dan, would not say that WS-* is more strictly typed than REST. I like REST, but in a way I find REST more restrictive than SOAP (Only five operations, what’s that all about?). As I’ve written in my WS-DuckTyping post, there are ways to deal with WS-* in a more flexible way.

What I do see is that REST is adopted by the same people who like scripting languages. In that aspect, REST and Ruby on Rails are in one camp, while SOAP and Java/.NET are in the other.

I guess it all comes down to the coolness factor: if you want to be cool, do REST and RoR; if you want to make money, do WS-* and Java. ;)

Comments (3)

« Previous entries ·