Wednesday, June 18, 2008

REST-ful services using JAX-WS 2.0

REST style services conform to a set of constraints and architectural principles
  • RESTful services are stateless. Each request from a client to a server must contain all the information necessary to understand the request and must not depend on any stored contextual information on the server.
  • REST-ful services have a uniform interface. For example for a RESTful HTTP service, the operation supported are GET, POST, PUT and DELETE.
  • REST based architectures are built from resources which are identified by unique URI's.
  • REST components manipulate resources by exchanging representations of the resources.


The fundamental differences between REST and RPC based services can be outlined as
  • RPC services work by invoking a procedure on a server rather than by exchanging representations of a resource.
  • In the RPC approach typically many operations are invoked at the same URI, which is fundamentally different from the REST way where every resource has a unique URI.




RESTful vs SOAP based services


Message Format


Interface Definition


Transport


XML XML inside a SOAP envelope
none WSDL
HTTP HTTP,FTP,MIME,JMS,SMTP etc

In order to consume a RESFful service using JAX-WS 2.0, the majority of the work needs to be done using the javax.xml.ws.Dispatch interface. The javax.ws.xml.Service interface is the abstraction which provides the client interface to a web service. Since RESTful services do not have WSDL representations, the way to deal is a bit awkward, however that is the way JAX-WS has been designed. We use the Service interface to create an instance of the javax.xml.ws.Dispatch interface. Dispatch is a low level API which allows users to create messages by working directly with XML rather than using high level API's like JAXB etc.

The following code displays the basics and is discussed below

QName svcQName = new QName("http://xyz", "svc");
QName portQName = new QName("http://xyz", "port");
Service svc = Service.create(svcQName);
svc.addPort(portQName, HTTPBinding.HTTP_BINDING, args[0]);
Dispatch dis =
svc.createDispatch(portQName, Source.class, Service.Mode.PAYLOAD);
Map requestContext = dis.getRequestContext();
requestContext.put(MessageContext.HTTP_REQUEST_METHOD, "GET");
Source result = dis.invoke(null);
try {
TransformerFactory.newInstance().newTransformer()
.transform(result, new StreamResult(System.out));
} catch (Exception e) {
throw new IOException(e.getMessage());
}
The web service url is as a command line argument(arg[0])
  • The client uses the Service.addPort() method to create a port within the Service instance that can be used to access the RESTful Web service.
  • Next, the Service.createDispatch() method is invoked to create an instance of Dispatch—a Dispatch instance that enables you to work with XML request/response messages as instances of javax.xml.transform.Source.
  • The Dispatch.invoke() method then packages the XML request—per the JAX-WS 2.0 HTTP Binding—and sends it to the RESTful service. The invoke() method waits for the response before returning.
  • The service processes the HTTP GET and sends an HTTP response that includes the XML.
  • The invoke() method returns the response XML message as an instance of Source.
The addPort() method takes a URI parameter that defines the transport binding. The default is SOAP over HTTP but for RESTful services we use the HTTPBinding.HTTP_BINDING. The type of payload is specified in the createDispatch() method. Generally when passing SOAP messages, Service.Mode.MESSAGE is used to indicate that you want to work with the complete SOAP envelope as opposed to just the SOAP body(PAYLOAD). In case of RESTful services since there is no enveloper, PAYLOAD mode is used.

The emperor and me beaching

The Devil next door

Kaiser The Emperor