Leveraging RESTful Services from Java applications using Jersey (Introduction) americas cup win 2682133k1

Leveraging RESTful Services from Java applications using Jersey (Introduction)

While researching for the Oracle SOA Suite 11g Handbook, I wanted to take a quick look at REST(ful) WebServices and see how those can be integrated into the SCA based SOA Composite Applications that we create with the Oracle SOA Suite. Currently, it does not have the HTTP binding that the 10.1.3 release of the SOA Suite used to have. So what are the alternatives? But first, how does one call a simple HTTP only (no SOAP/WS*) service from a piece of Java code? With as little programming and as much framework lifting as possible.

One of the frameworks available for RESTful operations is Jersey – a framework that should be more REST aware than plain HTTP communication oriented libraries like Apache HTTP Client, as well as offer some support for typical formats used in RESTful interactions, such as JSON, XML, RSS, CSV. So let’s create the simples Java application consuming a RESTful service – the Google Translation service – using the Jersey library.

The first steps are quite simple. A small test of the Google Translation API described at http://code.google.com/apis/ajaxlanguage/documentation/ and to be accessed at http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=hello%20world&langpair=en%7Cit. This service takes a string to translate and an indication of a source and a destination language. Though maybe not formally resource oriented enough to be called REST-style (or RESTful) service by some, it is a service that does not require SOAP or WS* but simply a HTTP Get request. So at least quite restful.

Calling this service can be done through ordinary means with a little bit of programming effort, or using frameworks – with a bit of configuration and Googling for examples.

I decide to use the Jersey framework, the Client part of the framework that is. Note that Jersey is frequently used to expose RESTful services – and that it also support the client, consumer end of things. That is the part I use in this article.

1. Download Jersey libraries

I browsed to https://jersey.dev.java.net/nonav/documentation/latest/user-guide.html#chapter_deps and downloaded jersey-archive-1.1.4.1.zip file. I extracted several libraries from that file to add to my project:  jersey-client.jar,  jersey-core.jar and  jsr311-api.jar.

2. Create a Java class to access the Google service using Jersey and print the translation result to the console:

package nl.amis.restclient;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import javax.ws.rs.core.MultivaluedMap;

public class TranslationClient {

  private static String googleTranslationService =
    "http://ajax.googleapis.com/ajax/services/language";

  private static String translateString(String sourceString, String sourceLanguage, String targetLanguage) {
    ClientConfig config = new DefaultClientConfig();

    Client c = Client.create(config);

    WebResource r = c.resource(googleTranslationService);
    MultivaluedMap<String, String> params = new MultivaluedMapImpl();

    params.add("v", "1.0");
    params.add("q", sourceString); // string to translate
    params.add("langpair",
               sourceLanguage+"|"+targetLanguage); // translation pair: from language and to language

    String response =
      r.path("translate").queryParams(params).get(String.class);
    return response;
  }

  public static void main(String[] args) {
    String response = translateString("hello world", "en", "it");
    System.out.println(response);
  }

}

Running this class produces the following output in the console:

{"responseData": {"translatedText":"ciao a tutti"}, "responseDetails": null, "responseStatus": 200}
Process exited with exit code 0.

Now I would like to have this JSON object parsed and turned into a proper Java object structure. It seems that the Jersey Client has support for this. And I really tried to find out how to make it work. I added the jersey-json-1.1.4.1.jar library. I added JAXB support to the project. I have created the DefaultConfiguration and added a JAXBContextResolver.class. I tried some JAXB annotations, I tried to a introduce a ResponseData class to morph the JSON response into.  I tried to discover how to create a MessageProvider or a MessageBodyWriter. I failed. I could not get it to work. The Jersey documentation failed me. And Google did so too.

So I decided to go for an easier solution: using the JSON-SIMPLE library it turned out quite simple to create a JSON object and access the translation result in a structured way.

1. Download the JSON-SIMPLE library from http://code.google.com/p/json-simple/ and copy json_simple-1.1.jar to my project.

2. Create a method that parses/inspects/retrieves from the JSON object created from the response from the Google Service:

  private static String extractTranslationFromJSON(String response) {
    final JSONObject jsonObj = (JSONObject)JSONValue.parse(response);
    String translation=null;
    if (jsonObj != null && jsonObj.containsKey("responseData")) {
      final JSONObject responseData = (JSONObject)jsonObj.get("responseData");
      translation=  responseData.get("translatedText").toString();
    }
    return translation;
  }

3. Update the main method to leverage this new method:

  public static void main(String[] args) {
    String response = translateString("hello world", "en", "it");
    System.out.println(response);
    System.out.println(extractTranslationFromJSON(response));
    System.out.println(extractTranslationFromJSON(translateString("hello world", "en", "de")));
    System.out.println(extractTranslationFromJSON(translateString("hello world", "en", "fr")));
    System.out.println(extractTranslationFromJSON(translateString("hello world", "en", "es")));
    System.out.println(extractTranslationFromJSON(translateString("hello world", "en", "fi")));
  }

4. Run the class. Here is the output from the console:

{"responseData": {"translatedText":"ciao a tutti"}, "responseDetails": null, "responseStatus": 200}
ciao a tutti
Hallo Welt
Bonjour tout le monde
hola mundo
Hei maailma
Process exited with exit code 0.

Conclusion

Using Jersey libraries, it is quite simple to make the HTTP requests required for accessing RESTful services. To process the reply from the service, I had a hard time leveraging the JSON support Jersey supposedly provides. Instead, I turned to JSON-SIMPLE. Given the simple, small and straightforward structure of the JSON response this will do for now. For a more complex service response, a mapping from JSON to a POJO structure would be nice.

Resources

Project sources: JerseyRestClient.zip.

Google Translation Service – documentation

Getting started with Jersey – https://jersey.dev.java.net/use/getting-started.html

Jersey Home page (for downloading software)

Consuming RESTful services using Jersey Client

Configuring Jersey Client for JSON

Using JSON Parser to interpret response (rather than Jersey mapping JSON via JAXB

JSON-SIMPLE project on Google Code – encode/decode JSON messages

Calling RESTful service without Jersey

Note: the non-Jersey based client for the RESTful service could be as simple (and messy) as:

package nl.amis.soasuite11g.mediator;

  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.io.OutputStreamWriter;
  import java.net.HttpURLConnection;
  import java.net.MalformedURLException;
  import java.net.ProtocolException;
  import java.net.URL;

public class SimpleHttpRequest {

// based on http://digiassn.blogspot.com/2008/10/java-simple-httpurlconnection-example.html

  private static String googleTranslationService =
    "http://ajax.googleapis.com/ajax/services/language/translate";
    /**
     * @param args
     */
    public static void main(String[] args) {
        HttpURLConnection connection = null;
        OutputStreamWriter wr = null;
        BufferedReader rd  = null;
        StringBuilder sb = null;
        String line = null;

        URL serverAddress = null;

        try {
            serverAddress = new URL(googleTranslationService +"?v=1.0&&q=hello%20world&&langpair=en%7Cit");
            //set up out communications stuff
            connection = null;

            //Set up the initial connection
            connection = (HttpURLConnection)serverAddress.openConnection();
            connection.setRequestMethod("GET");

            connection.setDoOutput(true);
            connection.setReadTimeout(10000);

            connection.connect();

            //get the output stream writer and write the output to the server
            //not needed in this example
            //wr = new OutputStreamWriter(connection.getOutputStream());
            //wr.write("");
            //wr.flush();

            //read the result from the server
            rd  = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            sb = new StringBuilder();

            while ((line = rd.readLine()) != null)
            {
                sb.append(line + '\n');
            }

            System.out.println(sb.toString());

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally
        {
            //close the connection, set all objects to null
            connection.disconnect();
            rd = null;
            sb = null;
            wr = null;
            connection = null;
        }
    }
    }

3 Comments

  1. Lucas Jellema November 13, 2011
  2. Karl-Petter Ã…kesson November 4, 2011
  3. sportechno August 9, 2011