RESTful Client with the Play Framework

BTI360 Blog / February 2, 2011 in 

Introduction

This week we are going to look at building a client for a RESTful Web Service using the Play Framework. The Play Framework is a relatively new open source web application framework written in Java. Play follows the model-view-controller pattern and aims to optimize developer productivity by emphasizing convention over configuration, hot code reloading, and targets RESTful architectures.

Setup

Initially we are going to follow the same steps we completed in our previous blog about building a RESTful Web Service with Play. We’ll call this project PlayDictionaryClient,
so let’s go ahead and create our application with the “play new PlayDictionaryClient” command. We are also going to re-use our RESTful Web Service Test App as a gui for our application and our Spring Dictionary Web Service as our RESTful Web Service.

Creating the GUI

For our GUI we will be using our RESTful Web Service Test app that we have used in previous blogs and screencasts. It will run outside of the Play Framework so we will need to drop the html+js+css files into the public directory. All files in this directory are served statically.

Creating our Controller

Let’s create our controller by extending the Controller class. We’ll need to also create four methods: getWords, addWord, updateWord, and deleteWord. We are also going to be using the WS module from the Play Framework which is simple HTTP client that can be used to make
web service requests.

First let’s look at our getWords method. This method is a GET request that will return all of the words in the dictionary.

public static void getWords() {
    String response = req.get().getString();
    if(format.equalsIgnoreCase("json")) {
    	renderJSON(response);
    } else if(format.equalsIgnoreCase("xml")){
    	renderXml(response);
    }
}

In all the code samples, the url variable is just the url of our web service. First off we need to determine what mime type the client is requesting. We can do this by checking the value of request.format, which the framework has populated by looking at the requests Accepts header. In this example the value will be either json or xml (These are two of the built-in mappings. If you use another media type that isn’t mapped you will need to do the header parsing and content negotiation on your own.). Next we create a WSRequest using the web service url and set the Accept header to the appropriate value. Then we can execute the GET request by calling get() and also call getString() to put the response body into our string variable. There are also getJson() and getXml() methods but in this instance we are simply acting as a middle man and do not need to do any processing on the data.

So at this point we have our data and need to send it to our client. We just check the format, and call the appropriate render method, which writes the data and sets the Content-Type header to either json or xml so our client knows what he is getting.

You can see that our dictionary contains four words and their names and definitions have been returned in json.

Next let’s look at the addWord method.

public static void addWord() throws IOException {
    StringBuffer out = new StringBuffer();
    byte[] b = new byte[4096];
    for (int n; (n = request.body.read(b)) != -1;) {
        out.append(new String(b, 0, n));
    }
    String format = request.format;
    WSRequest req = WS.url(url).setHeader("Content-Type", "application/" + format);
    req.body(out.toString());
    HttpResponse resp = req.post(); 
    response.status = resp.getStatus();
}

First we have some boiler-plate code that pulls the request body into a String. Again we don’t have to do any special parsing since the data is already in the correct format. We again access the static request variable, which is just an abstraction for the Http Request, and read the data from the body InputStream. Next we check the format and set the correct Content-Type header on our WSRequest. Then the data is written to the request body using the body() method and we call post() to get our HttpResponse. In this case our response should just be a 201 Created which we will just pass on to the client using the status variable of the response abstraction.

Our post this time was a new word in xml and on execution we receive a 201 letting us know that our new word has been created.

Our updateWord() method is nearly identical to our addWord method with one subtle difference.

Since the word name is our primary key, we must include the name as part of our url. Also successful PUTs will return a 200 OK response.

Now let’s look at the last method, deleteWord().

public static void deleteWord(String word) {
    WSRequest req = WS.url(url + word);
    HttpResponse resp = req.delete();
    response.status = resp.getStatus();
}

This one is very simple, we just take the word name that is passed into our method by the framework,
and call a delete request.

Route file

One last thing we need to do is all our methods to the routes config file. Can’t forget to do this or else our methods won’t be called and our requests will only get 404s. We just need to add four lines,

Previous

HTML5 and REST

Next

HTML5 History API and the Hashbang

Close Form

Enjoy our Blog?

Then stay up-to-date with our latest posts delivered right to your inbox.

  • This field is for validation purposes and should be left unchanged.

Or catch us on social media

Stay in Touch

Whether we’re honing our craft, hanging out with our team, or volunteering in the community, we invite you to keep tabs on us.

  • This field is for validation purposes and should be left unchanged.