Here, I will very briefly, present a simple example on making a REST service using the Play Framework (1.2.4) vs making a REST service using JAX-RS in java EE 6.
The goal is to enable us to compare the complexity and the amount of code to be written (to implement a REST service) in respectively Play and in Java EE 6. In both Play and Java EE 6, there are several ways to implement a REST service, so this presentation will (rather arbitrarily) choose one approach from each platform and present that.
In our example, we are creating a Library service exposing books of a library database as resources via REST.
We will represent a book resource with the following (directory structure like) URI:
http://mylibrary.com/library/books/{isbn}
The part {isbn}
above is the book's International Standard Book Number, and represents a dynamic part, replaced by the books isbn number.
An example request is:
http://mylibrary.com/library/books/0596529260
which in our example should return a JSON representation of the book as shown below (The JSON representation is deliberately made simple for legibility reasons.):
{
"isbn":"0596529260",
"title":"Restful Web Services",
"authors":[
{"firstName":"Leonard","lastName":"Richardson"},
{"firstName":"Sam","lastName":"Ruby"}]
}
How can we implement this in Play?
To make things work in Play we need to implement a Play controller (extending play.mvc.Controller
) and then configure URLs mappings
to the functions in the Play controller via the file conf/routes
located in Play's conf folder.
We name our Play controller Library
and its implementation is sketched below.
package controllers;
import play.*;
import play.mvc.*;
import models.*;
public class Library extends Controller {
public void static getBookByISBN(String isbn){
Book book = … look up book by isbn
renderJSON(book);
}
}
The Library
controller contains scripting to look up the book Book book = … look up book by isbn
(could be done using JPA)
and a call to an inbuilt function renderJSON(book)
to return the book formatted as JSON.
(In case we use JPA and for some reason need a transactional context, then Play is handling the transaction implicitly by executing the getBookingByISBN call within a transaction.)
The URL mapping, in the Play file conf/routes
, is shown below.
GET /library/books/{isbn} Library.getBookByISBN
The structure of the conf/routes
configuration line is to be read as: For HTTP GET
requests then map the URI path /library/books/{isbn}
to the class and function Library.getBookByISBN
.
Notice the name isbn
. It is, intentionally, the same name as the name of the parameter isbn
of the static method getBookByISBN
of the Library
controller. This is a general principle in the Play framework, called smart binding.
The rendered model objects are shown below. They are just simple POJOs (Plain Old Java Objects) but are shown here to complete the example. Again, the model objects are deliberately made simple for legibility reasons.
package models;
import java.util.*;
public class Book {
public String isbn;
public String title;
public List authors = new ArrayList();
}
package models;
public class Author {
public String firstName;
public String lastName;
}
That was, very briefly, one way to expose a REST service in Play!
Let's move on and see how we can implement the same example in Java EE 6 using JAX-RS annotations.
When possible, we will use the same names as in the Play example above to ease our comparison between the two examples. For the simplicity of the example, we will also reuse the POJOs from the Play example above.
The Java EE 6 example is packaged and deployed as a web application (war). (During development this is done automatically for you if you are using the Netbeans 7.1 IDE as I am).
Below I have shown what corresponds to the Library
controller in the Play example.
Notice it is a POJO with JAX-RS annotations. The POJO exists within the classpath of the web application.
package controllers;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import models.Author;
import models.Book;
@Path("/library")
public class Library {
@GET
@Path("/books/{isbn}")
@Produces("application/json")
public Book getBookByISBN(@PathParam("isbn") String isbn) {
Book b = … look up book by isbn
return b;
}
}
Notice, that all the URI path configuration to a class and method is done via the JAX-RS annotations: @Path("/library")
, @Path("/books/{isbn}")
. The mapping between the isbn part of the URI and the parameter isbn is done via the @PathParam("isbn")
annotation. The mapping to the GET
request is done via the annotation @GET
. The representation of the output as JSON is here done implicitely via the annotation @Produces("application/json")
.
(In case we need a transactional context, we could easily turn the POJO above into a stateless session bean by adding the annotation @javax.ejb.Stateless at the class level of the POJO.).
Now we need to add the following configuration snippet code shown below to the web.xml
of the web application. If you are using Netbeans 7.1, then this is done automatically by Netbeans for you.
<servlet>
<servlet-name>ServletAdaptor</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletAdaptor</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Again, job done, this was very briefly, one way to expose a REST service using Java EE 6.
In conclusion:
Amount of code: With respect to the amount of code to write to get up running, then based on the presentation above, I think it is fair to conclude that the two examples are kind of "equal".
Complexity: With respect to complexity it is more difficult to compare. It depends on our knowledge and experience with the two platforms.
If you look at the "learning curve" as an indicator of complexity between the two examples I think Play is less complex than Java EE 6. E.g. if you compare JAX-RS annotations with the conf/routes
configuration in Play, then based on the steepness of the implicit learning curve I think Play is less complex than JAX-RS. When using Java EE 6 you need some knowledge of the Java EE 6 platform and you need to know of the use and meaning of the different JAX-RS annotations.
Maybe the needed tooling used to create the examples can be used as an indicator of the implicit complexity of the examples. The Play example above was created using a terminal and a simple text editor (I used BBEdit). The Java EE 6 example above was created using the Netbeans 7.1 IDE. Netbeans hide away the complexity of the Java EE 6 platform. So, when looking at the tooling as an indicator of complexity, then Play is less complex than Java EE 6.
And that completes the presentation … :-)
7 comments:
Thanks for the nice post!
"web.xml" is optional in Java EE 6 and can be replaced with:
@javax.ws.rs.ApplicationPath("/*")
public class ApplicationConfig extends javax.ws.rs.core.Application {
}
Jersey will then register an implementation specific Servlet.
Hi Arun ... :-) Thx for your comment ... :-)
Your background hurts my eyes
Your background hurts my eyes
Your background hurts my eyes
Post a Comment