RESTful on Play! framework

As per request, a simple REST-like approach. It works almost the same way Codemwncis’ solution works but uses the Accept header for content negotiation. First the routes file:

GET     /user/{id}            Application.user
POST    /user/                Application.createUser
PUT     /user/{id}            Application.updateUser
DELETE  /user/{id}            Application.deleteUser

You don’t specify any content type here. Doing so is IMHO only necessary when you want to have “special” URIs for certain resources. Like declaring a route to /users/feed/ to always return in Atom/RSS.

The Application controller looks like this:

public static void createUser(User newUser) {
    newUser.save();
    user(newUser.id);
}

public static void updateUser(Long id, User user) {
    User dbUser = User.findById(id);
    dbUser.updateDetails(user); // some model logic you would write to do a safe merge
    dbUser.save();
    user(id);
}

public static void deleteUser(Long id) {
    User.findById(id).delete();
    renderText("success");
}

public static void user(Long id)  {
    User user = User.findById(id)
    render(user);
}

As you can see I only removed the getUserJSON method and renamed the getUser method. For different content types to work you now have to create several templates. One for each desired content type. For example:

user.xml:

<users>
  <user>
    <name>${user.name}</name>
    . . .
  </user>
</users>

user.json:

{
  "name": "${user.name}",
  "id": "${user.id}",
  . . . 
}

user.html:

<html>...</html>

This approach gives browsers always the HTML view, since all browsers send a text/html content type in their Accept header. All other clients (possibly some JavaScript-based AJAX requests) can define their own desired content type. Using jQuerys ajax() method you could do the following:

$.ajax({
  url: @{Application.user(1)},
  dataType: json,
  success: function(data) {
    . . . 
  }
});

Which should get you the details about User with the ID 1 in JSON format. Play currently supports HTML, JSON and XML natively but you can easily use a different type by either following the official documentation or use the content negotiation module.

If you are using Eclipse for development I suggest use the REST client plugin which lets you test your routes and their corresponding content type.

Leave a Comment