Monthly Archives: February 2006

REST Support in JAX-WS

I was intrigued by the REST support in JAX-WS. REST style could be very useful in certain situations,
not to mention the fact that there are already many REST-style services out there.

While I don’t want to get into SOAP vs. REST debate here I still want to quickly mention one
very important REST advantage, which is security.

Since each service call operation in REST is an HTTP GET URL, it makes it easy to use
traditional Web authorization schemes, including Apache mod_authnz or J2EE declarative security defined in web.xml.
Contrast that with SOAP, which requires looking inside the message to figure out what security policy should be applied.
Another side of it is auditing and monitoring. With REST I can easily see all the details of the requests to my web service
operations just by looking at the Web server’s access log and/or using one of the numerous log analysis tools.
SOAP does not give me this information automatically; different application servers and ESB products may provide these capabilities, but there is no guarantee (since it is not part of any specification).

In any event, REST has its place and so it’s nice to see that JAX-WS authors recognized it.

Unfortunately, upon closer examination, it turned out that REST support in JAX-WS is pretty shallow.
REST is really a second class citizen compared to SOAP. Here’s why I came to this conclusion:

  • Automatic WSDL generation (when using annotations in service implementation class) is not supported.
    I was expecting to see the support of HTTP GET binding defined in WSDL 1.1, but it is not there.
    In general, the spec does not mandate any WSDL to Java or Java to WSDL binding support for REST.
  • Object serialization/deserialization is not supported either. This is not unexpected since mapping of a complex object graph to name/value pair GET string may be non-trivial. But I don’t see a problem of doing it for simple flat objects that don’t have nesting.

  • Consequently, in order to use REST, one has to rely on dispatcher API on the client and so the query string has to be created manually. Same is happening on the server where developers have to use WebServiceContext and parse the query string manually.

In short, using REST requires some low-level programming; its support is clearly limited compared to SOAP.

What I would like to see is the ability to implement a RESTful service by simply adding
@BindingType(value=HTTPBinding.HTTP_BINDING)
annotation without having to make any other changes relative to a regular SOAP service (or client).
Clearly, we’re not there yet.

Tags: , ,

JAX-WS and Annotations: Looking Good

Lately I’ve been playing with
JAX-WS reference implementation
(version EA3).
JAX-WS is the next version of JAX-RPC (i.e., JAX-WS is renamed JAX-RPC 2.0) and it
comes with many interesting features, including annotations, HTTP binding, MTOM,
asynchronous client operation, direct access to XML stream (finally!) and others.

In this entry I will focus on
annotations
. Annotations allow developers to configure binding,
handler chains, set names of portType, service and other WSDL parameters.
This makes it possible to use “Java to WSDL” approach as the primary way for
developing Web services (for the server side).
Previously with JAX-RPC I was leery of this approach since it was
not possible to “fine tune” generated WSDL file.

Annotations greatly simplify Web services development process. For the server side,
JAX-WS only generates a wrapper class for the parameters of the service operation.
If “bare” (“unwrapped”) mode is used, then no code is generated and so this step can be
skipped completely (in other words, all annotations will be handled at run time).
This makes it easy to do all development from IDE, for example in my case I
deploy to Tomcat and I use Eclipse with Sysdeo plugin,
and so I was able to
change the code in my Web service class without
having to restart the server.

Changing annotations themselves does require bouncing the server, but still there is
no code generation involved and so there is no build file to run.

Note that code generation is still required for the client side unless dynamic API is used.

Finally, here is an example of a simple Web service that takes Person object
and returns concatenated full name.


import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

@WebService(
    // Name maps to PortType in WSDL. Default is the name 
    // of the class which is not very intuitive
    name = "PersonService",
    // by default, the namespace is derived from the Java package 
    // name which is not always desirable
    targetNamespace = "http://myarch.com/personservice",
    /* I use the "Endpoint" suffix as it is better convey the 
     * meaning of this parameter in WSDL and also since this 
     * will be the name of the "factory" class generated for the 
     * client side. The default is the name of the class + "Service"
     */
    serviceName="PersonServiceEndpoint"
)

/*        
 * Note that document/literal/wrapped is the default, but using  
 * "bare" as opposed to "wrapped" allows to avoid code generation.          
 */
@SOAPBinding(
    parameterStyle=SOAPBinding.ParameterStyle.BARE)
        
public class PersonServiceImpl {
    
    public java.lang.String produceFullName( Person person) {

        return person.getFirstName()+" "+person.getLastName();
    }
}

Tags: , ,