Leveraging RESTful Services from Java applications using Jersey (Introduction)

3

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;
        }
    }
    }
Share.

About Author

Lucas Jellema, active in IT (and with Oracle) since 1994. Oracle ACE Director for Fusion Middleware. Consultant, trainer and instructor on diverse areas including Oracle Database (SQL & PLSQL), Service Oriented Architecture, BPM, ADF, Java in various shapes and forms and many other things. Author of the Oracle Press book: Oracle SOA Suite 11g Handbook. Frequent presenter on conferences such as JavaOne, Oracle OpenWorld, ODTUG Kaleidoscope, Devoxx and OBUG. Presenter for Oracle University Celebrity specials.

3 Comments

  1. Karl-Petter Ã…kesson on

    Hi,
    stumbled upon this when I just tried to get a simple REST client to work. After lots of frustration yesterday I managed to get it to work today. The main issue, which I never understood from the error logs was that I didnt had correct libs loaded. But today I realized that and also discovered a documentation error on the Jersey sight. Firstly I just included only those required by JSON but realized that was just a subchapter of requirements for JAXB http://jersey.java.net/nonav/documentation/latest/chapter_deps.html#d4e1736 but in the list of jars needed one from Jackson was missing which I realized when reading this page http://wiki.fasterxml.com/JacksonDownload

    This post is a couple of years old but was good and helped me except the last steps so I hope my comment here can help someone discovering this later!
    /Karl-Petter