Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RESTful on Play! framework

People also ask

Is RESTful API a framework?

The REST API is part of the integration framework and handles requests from external consumers.

What is play framework used for?

Play Framework makes it easy to build web applications with Java & Scala. Play is based on a lightweight, stateless, web-friendly architecture. Built on Akka, Play provides predictable and minimal resource consumption (CPU, memory, threads) for highly-scalable applications.

What is RESTful API?

RESTful API is an interface that two computer systems use to exchange information securely over the internet. Most business applications have to communicate with other internal and third-party applications to perform various tasks.


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.


This is still a popular question, but the highest voted answers are not up to date with the current version of play. Here's a working REST example with play 2.2.1:

conf/routes:

GET     /users                 controllers.UserController.getUsers
GET     /users/:id             controllers.UserController.getUser(id: Long)
POST    /users                 controllers.UserController.createUser
PUT     /users/:id             controllers.UserController.updateUser(id: Long)
DELETE  /users/:id             controllers.UserController.deleteUser(id: Long)

app/controllers/UserController.java:

public static Result getUsers()
{
    List<User> users = Database.getUsers();
    return ok(Json.toJson(users));
}

public static Result getUser(Long id)
{
    User user = Database.getUser(id);
    return user == null ? notFound() : ok(Json.toJson(user));
}

public static Result createUser()
{
    User newUser = Json.fromJson(request().body().asJson(), User.class);
    User inserted = Database.addUser(newUser);
    return created(Json.toJson(inserted));
}

public static Result updateUser(Long id)
{
    User user = Json.fromJson(request().body().asJson(), User.class);
    User updated = Database.updateUser(id, user);
    return ok(Json.toJson(updated));
}

public static Result deleteUser(Long id)
{
    Database.deleteUser(id);
    return noContent(); // http://stackoverflow.com/a/2342589/1415732
}

Use Play! to do it all. Writing REST services in Play is very very easy.

Firstly, the routes file makes it straightforward to write routes that conform to the REST approach.

Then, you write your actions, in the controller, for each API method you want to create.

Depending on how you want to return the result (XML, JSON etc), there are a few methods you can use. For example, using the renderJSON method, allows the results to be rendered very easily. If you want to render XML, then you can just do so in the same way as you would build an HTML document in your View.

Here is a neat example.

routes file

GET     /user/{id}            Application.getUser(format:'xml')
GET     /user/{id}/json       Application.getUserJSON
POST    /user/                Application.createUser
PUT     /user/{id}            Application.updateUser
DELETE  /user/{id}            Application.deleteUser

Application file

public static void createUser(User newUser) {
    newUser.save();
    renderText("success");
}

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();
    renderText("success");
}

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

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

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

getUser.xml file

<user>
   <name>${user.name}</name>
   <dob>${user.dob}</dob>
   .... etc etc
</user>

Integrating with a JAX-RS implementation is a possible alternative approach to using Play's built-in HTTP routing. For a RESTEasy example, see the RESTEasy Play! module.

This approach makes sense if you are already invested in JAX-RS, or if you need some of the advanced features REST that JAX-RS provides such as content negotiation. If not, it would be simpler to just use Play directly to serve JSON or XML in response to HTTP requests.


you should have a look at

http://www.lunatech-labs.com/open-source/resteasy-crud-play-module

it's a module for play that automatically build a rest interface, just like the crud module automatically builds an admin area...


It does seem like this approach is broken in Play version 1.2.3. If you download the source done by @seb and mentioned earlier https://github.com/sebhoss/play-user-sample, the creation of a new user object using POST with a JSON object is no longer possible.

You need to have specific methods for creation done using with json and xml POSTs. Outlined here: https://groups.google.com/forum/#!topic/play-framework/huwtC3YZDlU