X

Implementing RESTful Web Services in Java

Guest Author

By Jakub Podlesak and Paul Sandoz

This Tech Tip will show you how to write RESTful web services in
Java that conform to the JAX-RS: Java API for RESTful Web
Services (JSR-311)
specification
and its reference implementation - Jersey. You'll learn some of the
principles of Representational State Transfer (REST) and get
introduced to JAX-RS and Jersey.

The tip uses a sample application to demonstrate some of the
JAX-RS concepts and techniques. You can obtain the sample
by downloading the latest Jersey snapshot from the Jersey
downloads page
.
The code examples in the tip are taken from the source
code of the sample application (which is included in the
download package).

An Introduction to RESTful Web Services

Representational State Transfer (REST) is a style of software
architecture for distributed systems such as the World Wide Web.
The term was introduced in the doctoral dissertation of
Roy Fielding in 2000, and has since come into widespread use in
the networking community. An important concept in REST is the
existence of resources, each of which can be referred to using
a global identifier, that is, a URI. In order to manipulate
these resources, components of the network, clients and servers,
communicate using a standardized interface such as HTTP and
exchange representations of these resources.

RESTful web services are services built using the RESTful
architectural style. Building web services using the RESTful
approach is emerging as a popular alternative to using
SOAP-based technologies for deploying services on the Internet,
due to its lightweight nature and the ability to transmit data
directly over HTTP.

RESTful Web Service Principles

A RESTful web service is based on the following principles:

  • Resources and representations. Instead of providing just one
    endpoint for a particular web service and having that
    endpoint perform various operations, you provide access to
    resources. A resource is a single piece of your web
    application that you make accessible to clients. Because the
    resources you have are not transportable over the network,
    "providing them" means providing representations of their
    state.

  • Addressability and connectedness. Resources have their
    representations, but providing representations of resources
    would be useless if you could not address them. In REST,
    every resource must have at least one address, that is, one
    URI. To address the resource, you simply specify the URI.
    This concept is called "addressability". By publishing your
    web application, you introduce many different URIs that are
    connected to each other. Because of that connectedness, the
    only URI you need to give to your clients is one URI called
    the "bootstrap URI".

  • Uniform interface. Even if you make resources available
    through URIs and representations to exchange between the
    client and server, it still does not allow you to establish
    communication. You need a communication protocol/interface to
    use. In a REST architecture, such an interface must be uniform.
    It means that whatever URI you access, the interface should be
    the same. For instance, on the World Wide Web no matter what
    URI (resource address) you enter, your web browser simply uses
    an HTTP GET method to retrieve a corresponding web page
    (resource representation) and displays it.

  • Statelessness. Statelessness means that a web application is
    not responsible for keeping any information about the state of
    its clients. REST does not encompass the concept of HTTP
    sessions. The client is responsible for tracking its own
    actions (if it needs to). The service maintains its resources
    and provides a uniform interface to the clients.

JAX-RS and Jersey

JAX-RS provides a standardized API for building RESTful web
services in Java. The API basically provides a set of
annotations and associated classes and interfaces. Applying
the annotations to Plain Old Java Objects (POJOs) enables you to
expose web resources. The API is not yet complete. The final
version should become part of Java EE 6. You can find more
information about JAX-RS in the jsr311 project.

Jersey is a reference implementation of JAX-RS. You can find
downloadable distributions of Jersey on the Jersey project
downloads page
.
If you select the latest Jersey snapshot and unzip it, you will
see that the Jersey implementation is bundled with several
examples demonstrating its use. Let's examine one of those
examples.

An Example of JAX-RS in Use: The Bookmark Application

One of the examples distributed with Jersey is a bookmark
application. You'll find it in the examples/Bookmark
subdirectory. The application uses the JAX-RS API to maintain
information about bookmarks saved by users. If you run the
application and specify a specific user, the application returns
data similar to the following:


   {sdesc":"test desc","userid":"testuserid","uri":

   "http://java.sun.com","ldesc":"long test description"}


Notice that the application returns the data in JavaScript
Object Notation (JSON)
format.

If you navigate below the examples/Bookmark subdirectory to
the resources subdirectory, you'll find the following resources
for the application:

  • UsersResource: Represents a list of users
  • UserResource: Represents a specific user
  • BookmarksResource: Represents a list of bookmarks for
    a specific user
  • BookmarkResource: Represents a specific bookmark

Recall that to address a resource in REST you specify its URI.
However, to communicate with a resource, you also need to
specify a communication protocol such as HTTP. Here are the URIs
and HTTP methods that correspond to the resources in the
Bookmark application:



 

class="vatop">





























class="headerpadding2">Resource
class="headerpadding2">URI Path
class="headerpadding2">HTTP Methods
UsersResource
/users
GET
UserResource
/users/{userid}
GET, PUT, DELETE
BookmarksResource
/users/{userid}/bookmarks
GET, POST
BookmarkResource
/users/{userid}/bookmarks/{bmid}
GET, PUT, DELETE
height="1" border="0" alt=" " />

 

To understand some of the basics of the JAX-RS, let's look
at two of these resources: UsersResource and UserResource.

UsersResource

Here is a snippet of source code from the UsersResource class:


   @UriTemplate("/users/")


   public class UsersResource {

     

       @HttpContext UriInfo uriInfo;    


       @PersistenceUnit(unitName = "BookmarkPU")

       EntityManagerFactory emf;


       /\*\* Creates a new instance of Users \*/

       public UsersResource() {

       }

    

       public List<UserEntity> getUsers() {

           return emf.createEntityManager().createQuery(

                  "SELECT u from UserEntity u").getResultList();

       }

    

       @UriTemplate("{userid}/")

       public UserResource getUser(@UriParam("userid") 

              String userid) {

           return new UserResource(

                  uriInfo, emf.createEntityManager(), userid);

       }


       @HttpMethod("GET")

       @ProduceMime("application/json")

       public JSONArray getUsersAsJsonArray() {

           JSONArray uriArray = new JSONArray();

           UriBuilder ub = null;

           for (UserEntity userEntity : getUsers()) {

               ub = (ub == null) ? 

                      uriInfo.getBuilder() : ub.clone();

               URI userUri = ub.

                       path(userEntity.getUserid()).

                       build();

               uriArray.put(userUri.toString());

           }

           return uriArray;

       }

   }

Notice that the UsersResource class is annotated by the
@UriTemplate("/users/") annotation. @UriTemplate is a JAX-RS
annotation that identifies the URI path for the resource. Here
the annotation identifies the URI path as /users/:


   @UriTemplate("/users/")

Annotating the class with a @UriTemplate annotation makes the
class a "Root resource class." It also means that for client
requests that access the /users/ URI path, this resource is
responsible for providing appropriate responses. Note too that
the /users/ URI path is the bootstrap URI path for the entire
Bookmark web application.

Another JSR-311 annotation in the UsersResource class is
@HttpContext.


   @HttpContext UriInfo uriInfo;

This annotation injects information into a class field or method
parameter. In the UsersResource class, @HttpContext injects
information about the URI into the uriInfo variable, which is
then available to provide pertinent information about the URI.

UsersResource Methods

The UsersResource class has two methods, getUser and
getUsersAsJsonArray. For the moment, let's skip getUser and
focus on getUsersAsJsonArray. The getUsersAsJsonArray method
returns the URIs for all user resources. Notice that the
method is annotated with two JSR 311 annotations: @HttpMethod
and @ProduceMime. The @HttpMethod annotation indicates that
the annotated method should be used to handle HTTP requests.
The annotation also specifies the type of HTTP request to
which the method will respond. In this example, the annotation
specifies that the getUsersAsJsonArray method serves HTTP GET
requests.


   @HttpMethod("GET")

Methods like this that serve REST requests are called "Resource
methods".

The @ProduceMime annotation specifies the MIME types that a
method can produce. Here, the annotation specifies that the
getUsersAsJsonArray method returns a JSONArray object containing
an array of URIs for all existing user resources.


   @ProduceMime("application/json")








Get Users Resources
Get Users Resources



 

The JSON array object that the method returns to a client might
look like this:


   ["http://localhost:8080/Bookmark/resources/users/joe", 

   "http://localhost:8080/Bookmark/resources/users/mary"]

This JSON array contains URIs, that is, links, to two user
resources, joe and mary.

The getUser method gets information about a specific user. For
example, if a client wants to get information about user joe,
the client accesses the resource at its URI -- in this case,
http://localhost:8080/Bookmark/resources/users/joe. Recall that
the UsersResource class serves all requests for paths beginning
with /users/, including the URI path for joe, that is,
/users/joe.

Here it's important that the getUser method is annotated with
@UriTemplate("{userid}/"). This makes the method a "Sub-resource
locator". Also the getUser method is annotated with @UriParam.
As a result, when the getUser method is invoked, a userid from
the current request URI path is injected into the userid
parameter.

Notice that there is no @HttpMethod annotation associated with
the getUser method. Because of that, the output of the method is
considered a Resource class object. This means that request
processing will be delegated to the Resource class and
appropriate @HttpMethod-annotated methods will be looked up
there. Because the getUser method returns a UserResource object:


   public UserResource getUser(@UriParam("userid") 

                 String userid) {

           return new UserResource(...)

an appropriate method in the UserResource class is invoked.








Get User Resources
Get User Resources



 

UserResource

As just mentioned, request processing for the getUser method in
the UsersResource class is delegated to an appropriate method in
a newly instantiated UserResource object. Here is a snippet of
code from the UserResource class showing one of its methods,
getUser.


   @HttpMethod("GET")

   @ProduceMime("application/json")

   public JSONObject getUser() throws JSONException {

       if (null == userEntity) {

           throw new NotFoundException(

                  "userid " + userid + "does not exist!");

       }

       return new JSONObject()

           .put("userid", userEntity.getUserid())

           .put("username", userEntity.getUsername())

           .put("email", userEntity.getEmail())

           .put("password", userEntity.getPassword())

           .put("bookmarks", 

                uriInfo.getBuilder().path("bookmarks").build());

    } 

Notice that this method also is annotated by @HttpMethod("GET")
and @ProduceMime("application/json"). Here the getUsers method
serves HTTP GET requests and returns a JSONObject object.
The JSONObject object contains a representation of a particular
user, for instance, the representation of the user whose userid
is joe.

You're encouraged to examine the rest of the source code in
UserResource. You'll notice additional JSR 311 annotations, such
as @ConsumeMime, which identifies the MIME types that a method
can accept.

Building and Deploying the Sample Code

The sample code for the tip is available as a NetBeans project.
You can build an deploy the sample from the NetBeans IDE or from
the command line. In either case:


  1. If you haven't already done so, download and install
    GlassFish V2.

  2. Download the latest Jersey snapshot from the
    Jersey downloads page
    and extract its contents. You should now see the newly
    extracted directory as <sample_install_dir>/jersey, where
    <sample_install_dir> is the directory where you installed the
    sample application. For example, if you extracted the
    contents to C:\\ on a Windows machine, then your newly created
    directory should be at C:\\jersey.

Building and Deploying the Sample Code in NetBeans


  1. If you haven't already done so, download and install
    the NetBeans 5.5.1 IDE.

  2. Start the NetBeans IDE. If you haven't already done so,
    register GlassFish V2 in NetBeans as follows:

    • Right click on Servers node in the Runtime window.
    • Select Add Server.
    • Leave the Server as Sun Java System Application Server.
    • Click the Next button.
    • Click the Browse button and browse to the location that you installed GlassFish V2.
    • Click the Choose button.
    • Click the Next button.
    • Set the Admin Password to the default, adminadmin, unless
      you chose a different password for GlassFish.
    • Click the Finish button.



  3. Open the Bookmark project as follows:

    • Select Open Project from the File menu.
    • Browse to the Bookmark subdirectory.
    • Click the Open Project Folder button.



  4. Build and deploy the Bookmark project as follows:

    • Right click the Bookmark project node in the Projects window.
    • Select Deploy Project or press F6 (Run Main Project).


Building and Deploying the Sample Code From the Command Line


  1. Set the AS_HOME environment variable to the GlassFish v2 installation
    directory, for example, (here shown in bash syntax):


          export AS_HOME= <GF_install_dir>


    where <GF_install_dir> is the directory where you installed
    GlassFish v2.


  2. Navigate below the <sample_install_dir>/jersey directory to
    the /examples/Bookmark directory. Build the Bookmark
    application by entering the following command on the command
    line (here shown in bash syntax):


          AS_HOME/lib/ant/bin/ant run-on-glassfish


Running the Sample Code

You can run the deployed Bookmark application as follows using
Curl, a command line HTTP tool.


  1. If you haven't already done so, download Curl.

  2. Add a new user by entering the following command on the
    command line (note that the commands in this and subsequent
    steps are shown on multiple lines for formatting purposes):


          curl -i --data "{\\"userid\\":\\"techtip\\",\\"username\\":

          \\"TechTip User\\",\\"email\\":\\"techtip@example.com\\",

          \\"password\\":\\"TEST\\"}" -H Content-type:application/json 

          -X PUT 

          http://localhost:8080/Bookmark/resources/users/techtip/



    In response, an HTTP GET request is dispatched to the getUser
    method in the UsersResource class, which instantiates a new
    UserResource object. The request is further dispatched to the
    putUser method.


    You should see output similar to the following:


          HTTP/1.1 204 No Content

          X-Powered-By: Servlet/2.5

          Server: Sun Java System Application Server 9.1_01

          Date: Thu, 01 Nov 2007 14:31:53 GMT



  3. Get a list of users by entering the following command on the
    command line:


          curl -i -X GET 

          http://localhost:8080/Bookmark/resources/users/



    This invokes the getUsersListAsJson method of the
    UsersResource class.


    You should see output similar to the following:


          HTTP/1.1 200 OK

          X-Powered-By: Servlet/2.5

          Server: Sun Java System Application Server 9.1_01

          Content-Type: application/json

          Transfer-Encoding: chunked

          Date: Thu, 01 Nov 2007 14:34:07 GMT


          ["http:\\/\\/localhost:8080\\/Bookmark\\/resources\\/users\\

          /techtip"]



  4. Get the representation of a user by entering the following
    command on the command line :


          curl -i -X GET 

          http://localhost:8080/Bookmark/resources/users/techtip/



    The resulting actions here are similar to those for step 2.


    You should see output similar to the following:


          HTTP/1.1 200 OK

          X-Powered-By: Servlet/2.5

          Server: Sun Java System Application Server 9.1_01

          Content-Type: application/json

          Transfer-Encoding: chunked

          Date: Thu, 01 Nov 2007 14:35:38 GMT


          {"userid":"techtip","username":"TechTip User",

          "email":"techtip@example.com","password":"TEST",

          "bookmarks":"http:\\/\\/localhost:8080\\/Bookmark\\/resources

          \\/users\\/techtip\\/bookmarks"}


Summary

This tip demonstrated how you can write RESTful web services in
Java that conform to the JAX-RS: Java API for RESTful Web
Services (JSR-311) specification. You can learn more about
JAX-RS in the jsr311 project. You
can learn more about Jersey, the reference implementation of
JAX-RS, in the Jersey project.

About the Authors


Jakub Podlesak is a member of the Jersey project team. Previously,
he participated in the development of Metro, the GlassFish v2
web services stack, as a member of the WS-Policy team.

Paul Sandoz is the co-spec lead and implementation lead for
JSR 311: Java API for RESTful Web Services. He has participated
in the W3C, ISO, and ITU-T standards organizations and
contributed various performance-related technologies and
improvements to the GlassFish web services stack, particularly
in standardization, implementation, integration, and
interoperability of Fast Infoset.

Join the discussion

Comments ( 11 )
  • ILANGO Thursday, May 29, 2008

    how to building and deploying the sample code from command line using tomcat.


  • Jakub Podlesak Monday, June 2, 2008

    I have not tested it, but you can try to deploy the war created (after you type ant) in Bookmark/dist subdirectory. I do not know how to configure jdbc resources on Tomcat, but it should be probably described in it's docs.

    However, if you haven't played with GlassFish yet, i think it is worth to give it a try and the example should work on it just fine;-)

    If you still want some very simple example -- without any db related stuff (which will run on Tomcat for sure), please look at http://blogs.sun.com/japod/entry/building_simple_jersey_web_app


  • LetsAsk Monday, July 14, 2008

    Would you please put a tutorial on how to use PUT and POST methods with mysql as a database?

    It would be great help for somebody like me who is new to this idea.

    I have seen everybody talking about GET in details but not more on PUT and POST.

    Thanks


  • EdO Monday, July 14, 2008

    Thanks for the feedback. I'm the manager of the Tech Tips program for SDN. I'll definitely pursue your suggestion for a future Tech Tip.


  • ilango Tuesday, August 5, 2008

    I created web service using Rest.I put all java class files(server Rest files) in one machine.Then i put all javascript files(client Rest files) in another machine.

    I can't access from one machine to another machine through Rest.If i put all the files in single machine, the Rest service work fine.Please give me the solution for

    above problem.It is very urgent


  • Jakub Monday, August 11, 2008

    hi ilango, please look at http://blogs.sun.com/japod/entry/workarounding_cross_domain_restriction_with

    for a solution. i hope it helps you


  • Alex Wednesday, August 20, 2008

    It would be great if this tutorial was IDE and AppServer agnostic.

    It would help if the tutorial explained the architecture of JAX-RS and how the code gets translated into something I can deploy on a webserver.

    I guess I'll go dissect the ant file...

    Any chance you could recreate this tutorial using Maven 2? Would save much time for others attempting to set up their dev environment.

    Thanks,

    Alex


  • Alex Wednesday, October 1, 2008

    Alex,

    I was thinking the same thing. I don't use, nor wish to use NetBeans (yes, I have it installed. We prefer and use Eclipse, and write our own ant tasks for dist builds).

    I can't find any good info on how to actually deploy a Jersey JAX-RS Web Service from scratch.

    Their examples from the command line work great, except they use the embedded lightweight http server and some proprietary method of getting the annotations to get parsed properly


  • Jakub Monday, October 6, 2008

    Hi Alex, you might want to check this post: http://blogs.sun.com/japod/entry/building_simple_jersey_web_app

    which shows how to use pure maven to build up a Jersey based REST web application. It uses slightly obsolete 0.8-ea version of Jersey, but is should give you the basic understanding how things work. With currently available 1.0-SNAPSHOT Jersey version, you will e.g. need to use @Produces annotation instead of @ProduceMime in your resource class.

    We plan to publish an updated tech tip on Jersey in about a month.


  • Ashish Monday, February 2, 2009

    Pleae let me know how to write the method which accept pathparam and queryparm both...


  • Jakub Wednesday, February 4, 2009

    You can use the following:

    @GET @Produces("text/plain")

    @Path ("{id}")

    public String getString(@PathParam("id") String id, @QueryParam("q") String q) {

    return String.format("path param id: %s, query param q: %s", id, q);

    }

    Also please note, the annotations have changed. For more recent information on JAX-RS and Jersey, you might want to check Jersey project home page https://jersey.dev.java.net/

    There is also a more recent tech tip published at http://blogs.sun.com/enterprisetechtips/entry/configuring_json_for_restful_web


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.