Steve Loughran and Edmund Smith of HP Labs have written an interesting piece on JAX-RPC and JAXM that discusses their suitability as programming models for Web services. Unfortunately much of their article ignores the advances we've made with JAX-WS (nee JAX-RPC 2.0). As co-spec lead for JAX-WS, I'd like to point out a couple of the salient features.

Much of the paper's thesis centres on the difficulty of XML<->Object mapping. I agree that this is a difficult problem - I'm not a member of the JAXB expert group but I've monitored the mailing list and have been regularly befuddled by the complexity of this undertaking. <grin>Fortunately that's now JAXB's problem not JAX-WS's</grin>. Using JAXB, JAX-WS still provides a WSDL<->Java capability as in JAX-RPC 1.1 (though now with support for all of XML Schema rather than a subset). However the JAX-WS EG recognized that in some (or many, depending on your perspective) cases working at the XML layer is useful/desirable and so we added a couple of XML-centric APIs that completely bypass the XML<->Object layer of the stack:Dispatch and Provider.

Dispatch is the client side API and uses the generic functionality introduced in J2SE 5.0 to offer an API that allows the developer to choose their abstraction. Developers can work with entire messages or message payloads either using XML APIs or using pre-cooked JAXB classes. Here are few examples:

Message payload using XML APIs:

javax.xml.transform.Source reqMsg = ...;
Service service = ...;
Dispatch<Source> disp = service.createDispatch(portName,
    javax.xml.transform.Source.class, PAYLOAD);
Source resMsg = disp.invoke(reqMsg);

Working directly with SOAP messages using XML APIs:

javax.xml.transform.Source reqMsg = ...;
Service service = ...;
Dispatch<Source> disp = service.createDispatch(portName,
    javax.xml.transform.Source.class, MESSAGE);
Source resMsg = disp.invoke(reqMsg);

Working with SAAJ SOAP messages:

javax.xml.soap.SOAPMessage soapReqMsg = ...;
Service service = ...;
Dispatch<SOAPMessage> disp = service.createDispatch(portName,
    javax.xml.soap.SOAPMessage.class, MESSAGE);
SOAPMessage soapResMsg = disp.invoke(soapReqMsg);

Finally, if you want to use JAXB separate from JAX-WS, message payload using JAXB objects:

JAXBContext jc = JAXBContext.newInstance("primer.po");
Unmarshaller u = jc.createUnmarshaller();
PurchaseOrder po = (PurchaseOrder)u.unmarshal(
    new FileInputStream( "po.xml" ) );
Service service = ...;
Dispatch<Object> disp = service.createDispatch(portName, jc, PAYLOAD);
OrderConfirmation conf = (OrderConfirmation)disp.invoke(po);

The Provider interface is the server side couterpart to Dispatch, here are a few illustrative examples:

Working with XML APIs to send a canned reply to every message:

@ServiceMode(value=Service.Mode.PAYLOAD)
public class MyService implements Provider<Source> {
    public MyService {
    }
    
    public Source invoke(Source request, Map<String,Object> context)
        throws RemoteException {
        Source requestPayload = request.getPayload();
        ...
        String replyElement = new String("<n:ack xmlns:n='...'/>");
        StreamSource reply = new StreamSource(new StringReader(replyElement));
        return reply;
    }
}

Simple echo service working with SAAJ SOAP messages:

@ServiceMode(value=Service.Mode.MESSAGE)
public class MyService implements Provider<SOAPMessage> {
    public MyService {
    }
    
    public SOAPMessage invoke(SOAPMessage request, Map<String,Object> context)
        throws RemoteException {
        return request;
    }
}

Using JAXB to read the input message and set the reply:

@ServiceMode(value=Service.Mode.PAYLOAD)
public class MyService implements Provider<Source> {
    public MyService {
    }
    
    public Source invoke(Source request, Map<String,Object> context)
        throws RemoteException {
        JAXBContent jc = JAXBContext.newInstance(...);
        Unmarshaller u = jc.createUnmarshaller();
        Object requestObj = u.unmarshall(request);
        ...
        Acknowledgement reply = new Acknowledgement(...);
        return new JAXBSource(jc, reply);
    }
}

Hopefully this taste of the new APIs will encourage everyone to check out the document centric features of JAX-WS.