Making asynchronous call to REST service

In the Using javax.xml.ws.Dispatch for REST Client entry i talked about how you can use the javax.xml.ws.Dispatch class for making call to the REST service. As you can see it makes calling the REST service difficult and it might not make sense to use this approach for calling service in most cases but it might be good idea to think about this approach when you want to make asynchronous calls, i wanted to try this approach so i made following changes to the DispatcherTest1.java

package com.webspherenotes.jaxrs;

import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.http.HTTPBinding;

public class DispatcherTest1 {

  public static void main(String[] args) {
    try {
      QName serviceName = new QName("http://www.webspherenotes.com/rest", "svc");
      QName portName = new QName("http://www.webspherenotes.com/rest", "port");
      Service svc = Service.create(serviceName);
      svc.addPort(portName, HTTPBinding.HTTP_BINDING, 
   "http://localhost:9080/MyWebService/rest/contact/1");
      Dispatch dis =
        svc.createDispatch(portName, Source.class, Service.Mode.PAYLOAD);
      Map requestContext = dis.getRequestContext();
      requestContext.put(MessageContext.HTTP_REQUEST_METHOD, "GET");
      
      Future f= dis.invokeAsync(null, new DemoAyncHandler());
      System.out.println("After making async call to request");
      f.get();
    
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

  }

}
We have to change only couple of lines here, first change the Dispatcher method that your calling from invoke to invokeAsync. The invokeAsync method returns object of java.util.concurrent.Future, calls its get method so that the current thread does not end before it gets calls response callback. Then create DemoAsyncHandler class that gets called when the response for REST service is ready.


package com.test;

import java.util.concurrent.ExecutionException;

import javax.xml.transform.Source;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Response;

public class DemoAyncHandler implements AsyncHandler{

  @Override
  public void handleResponse(Response response) {
    try {
      System.out.println("Inside DemoAsyncHandler.handleResponse "
   + response);
      Source source = response.get();
      XMLHelper.prettyPrintXML(source, System.out);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

}
Only thing that i am doing in the DemoAsyncHandler is to print the response on console, this is how the output looks like

Pretty print XML document

I use the following XMLHelper.java code whenever i have a requirement to pretty print XML, it can handle String, Document and Source, the common objects that i need to print


package com.webspherenotes.xml;

import java.io.OutputStream;
import java.io.StringReader;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;

public class XMLHelper {

  public static void prettyPrintXML(Source source, OutputStream stream) {
    try {
      Transformer transformer = TransformerFactory.newInstance()
          .newTransformer();
      transformer.setOutputProperty(OutputKeys.INDENT, "yes");
      transformer.
   setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
      transformer.transform(source, new StreamResult(stream));
    } catch (Exception e) {
      e.printStackTrace(System.out);
    }
  }
  
  public static void prettyPrintXML(Document doc, OutputStream stream) {
    prettyPrintXML(new DOMSource(doc),stream);
  }
  
  public static void prettyPrintXML(String xmlString, OutputStream stream){
    prettyPrintXML(new StreamSource(new StringReader(xmlString)),stream);
  }
}

Using javax.xml.ws.Dispatch for REST Client

The JAX-WS has a javax.xml.ws.Dispatch class that you can use for making HTTP call, So i can use it even for making call to REST service and i wanted to see how that works. I do have a Contact REST service that allows me to make CRUD calls on the Contact table, For example i can call http://localhost:9080/MyWebService/rest/contact/1 URL to get a record from CONTACT table where contact Id is 1. This is the output i get when i call it for contactId 1
The REST service returns CONTACT object in XML format for contactId equal to 1, I wanted to try making the same call using the javax.xml.ws.Dispatch object, this is the code that i built for it.

package com.webspherenotes.rest;

import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.http.HTTPBinding;

public class DispatcherTest1 {

  public static void main(String[] args) {
    QName serviceName = new QName("http://www.webspherenotes.com/rest", "svc");
      QName portName = new QName("http://www.webspherenotes.com/rest", "port");
      Service svc = Service.create(serviceName);
      svc.addPort(portName, HTTPBinding.HTTP_BINDING,
   "http://localhost:9080/MyWebService/rest/contact/1");
      Dispatch dis =
        svc.createDispatch(portName, Source.class, Service.Mode.PAYLOAD);
      Map requestContext = dis.getRequestContext();
      requestContext.put(MessageContext.HTTP_REQUEST_METHOD, "GET");
      Source responseSource = dis.invoke(null);
     XMLHelper.prettyPrintXML(responseSource, System.out);
  }
}
In this class first i am creating a Service object pointing to http://localhost:9080/MyWebService/rest/contact/1 URL and then i am getting the Dispatcher object pointing to it. Next i use the RequestContext object to set the HTTP request method to GET and then i call the Dispatcher.invoke() which actually makes HTTP request and it returns Source object representing the response. Once i have the response i am uing the XMLHelper.prettyPrintXML() for pretty printing the XML, this is how the output looks like