Implementing RESTful Web Services in Java

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:

 
Resource
URI Path
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
 

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.

Comments:

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

Posted by ILANGO on May 29, 2008 at 03:26 PM PDT #

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

Posted by Jakub Podlesak on June 02, 2008 at 12:19 AM PDT #

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

Posted by LetsAsk on July 13, 2008 at 08:16 PM PDT #

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.

Posted by EdO on July 14, 2008 at 02:01 AM PDT #

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

Posted by ilango on August 04, 2008 at 11:07 PM PDT #

hi ilango, please look at http://blogs.sun.com/japod/entry/workarounding_cross_domain_restriction_with
for a solution. i hope it helps you

Posted by Jakub on August 10, 2008 at 11:24 PM PDT #

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

Posted by Alex on August 20, 2008 at 06:38 AM PDT #

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

Posted by Alex on October 01, 2008 at 05:13 AM PDT #

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.

Posted by Jakub on October 05, 2008 at 07:44 PM PDT #

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

Posted by Ashish on February 02, 2009 at 06:42 AM PST #

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

Posted by Jakub on February 03, 2009 at 08:52 PM PST #

Post a Comment:
Comments are closed for this entry.
About

edort

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today