Skip to content

Play! And Hibernate – How To Get Running With Your JSON REST API

At some point you need some persistence. In my case, I need a central online place for all the Monsters my players will create and fight with. I need them centrally managed instead of locally on their devices.

My very intuitive approach was to make the information available via a REST API.

Here is how I did it. Setting it up on Play! is as easy as the name indicates.

If you are new to Play!, don’t worry I will also cover the configuration part in this series.

Resource Planning

Important enough when you want to design a REST API is the question “What kind of Resources do I need?”. Even when you only need a simple API for testing it is a good training to actually put some thought into it. As a best practice rule there are two kinds of resources you should model out:

  1. List or Collection Resources
  2. Instance Resources

Now you usually want to define which HTTP methods you want to allow on your resources. You know them… but for the sake of completeness:

  • GET
  • POST
  • PUT, DELETE, HEAD, OPTIONS, TRACE, CONNECT

Well, for our proof of concept purposes GET and POST methods will be sufficient. In case your Google doesn’t find it, here is the link to the HTTP 1.1 specification if you don’t know the other ones.

Resource Patterns

Ok, what I want to do in my game is first, to create a Monster of a specific type and second, to retrieve it later given an identifier or context. My resources will look the following way:

Allowed Method
Resource Type
Resource URL
Description
GET, POSTCollection/playerId/monsters/The root monsters resource. Allows creating a new Monster (element) in the collection via POST or retrieval of all Monsters (list elements) via GET.
GETInstance/playerId/monsters/monster/resourceIdRetrieve the monster by its very unique resource URI

This is all we need for now.

For more information on resource design: This answer on SO is awesome.

Now I have my URLs how should I use them now? How to create a monster? And how does my iOS or HTTP client know the concrete URI for a monster?

Don’t worry, there is a pattern. Actually there are two flavours of the pattern. The core is similar but some tiny details differ.

Flavour One:

  1. Invoke a HTTP POST /playerId/monsters/ on the list resource in order to create a new monster, already sending some information about the monster (e.g. its type)
  2. The response is a 201 Created, with the HTTP Location header already pointing to /playerId/monsters/monster/resourceId
  3. The client invokes a redirect GET /playerId/monsters/monster/resourceId and collects the monster information
  4. The client might wants to bookmark the link to the monster for later retrieval or even cache it, depending on the servers cache directives

In our case we should not allow caching, as this would allow Proxies to store that information. As we supply authenticated content later on per player, we don’t want that information being cached.

The sequence diagram for Flavour One should make the pattern more understandable.

Flavour Two:

Not as pragmatic as Flavour One but more reliable and stable. It actually uses all HTTP verbs in conjunction with their intention.

  1. Invoke a HTTP POST /playerId/monsters/ with an empty body
  2. The response is a 201 Created, with the HTTP Location header already pointing to /playerId/monsters/monster/resourceId
  3. The client invokes a redirect GET /playerId/monsters/monster/resourceId and collects the monster information, usually this is an empty monster template (the server didn’t know what to create)
  4. The client having the empty monster representation fills the preferred type and additional information if needed
  5. The client PUTs the updated monster representation to /playerId/monsters/monster/resourceId

Flavour Two puts the information delivery to the end. The advantage here is that we leverage that POST is per specification not idempotent, but PUT is. So in case of an error in Flavour One Step 1, POSTing again creates a new resource all the time with given information.

In Flavour Two we only would create a cheap empty monster resource. And in case the PUT request fails on the created monster we can re-request it without a problem, as the PUT request is idempotent.

Additionally, when Etags come into play, the PUT request could always check against that for consistency reasons, in case another client updates the same resources in parallel.

It is up to you what you use here. I like both approaches, as usual it depends on your requirements which one to use. For my simple case here, I will use Flavour One.

Summary

Here is what I want my server to be capable to do by using the Play Framework:

  1. Receive a clients POST request that creates a monster, given a specific monster type
  2. The monster is an abstract class and is extended by specifically typed monster classes
  3. Create and persist the monster resource on server side using JPA (Java Persistence API)
  4. Return a 201 Created to the client with a Location header pointing to the created monster resource
  5. Receive a clients GET request in order to retrieve the created monster
  6. Query the monster using JPA from the H2 in-memory database
  7. Use Play!s capabilities and transform the Monster Java object to a JSON representation
  8. Return 200 OK with the JSON representation of the monster object

The next post will outline how to initially setup Play.

Then we go further and see how to code our REST API and use JPA with abstract classes for data persistence and retrieval.