An Introduction to Creating RESTful Web Services Using Jersey and Java
Introduction
I'm learning how to create RESTful web services using Sun's Jersey reference implementation of JAX-RS, the Java API for RESTful web services. Sun's RESTful Web Services Developer's Guide provides instructions on how to use Jersey and has many sample applications. Unfortunately, the instructions are centered around using the GlassFish enterprise server and the NetBeans IDE. My development environment is Eclipse and Tomcat so I needed to create my own example applications with instructions on how to build and deploy RESTful web services using that development environment. I thought it might be useful for other Java developers who are learning to use Jersey and RESTful web services to have examples ready-made for Eclipse and Tomcat.
As I mentioned above, I'm just learning how to use Jersey and RESTful web services so feel free to comment below if I've screwed something up. This first article will be just an introduction to creating and setting up a very simple RESTful web service. Along the way I'll explain the basic JAX-RS annotations that turn a Plain-Old-Java-Object (POJO) into a web service that can be called using the HTTP protocol.
Example Application
You can download the example application here. This download is an archived Eclipse - Maven project. I'm using Eclipse 3.3.2 Enterprise Edition with the Web Tools Platform and Maven plugins. The Java JDK I'm using with Eclipse is JDK 1.6.0_11 and the compiler compliance level is set to 6.0.
To load the project into Eclipse, just do File - Import - Existing Projects into Workspace (under General folder), click Next. Click on the Select Archive file radio button and click on the browse button. Navigate to where you downloaded the above archive (.zip file), select helloWS.zip and click Open. You should see helloWS under the projects window. Click Finish. Maven will download any jars specified as dependencies and Eclipse will rebuild the project.
Note that in the Maven pom.xml file are specified the dependencies needed for Jersey. The basic jar files Maven will download to your local repository are: jersey-server-1.1.0-ea.jar, jersey-core-1.1.0-ea.jar, jsr311-api-1.1.jar, and asm-3.1.jar. If you don't have Maven you can download and include those jars in your project. See the Jersey dependencies web page.
I use Tomcat 6 as my Java web application container. To run the example application using Tomcat, do the following: In Eclipse click on the project name then select Run - Run As - Run on Server. Configure your Tomcat 6 server if you've not previously done that. Eclipse will start up Tomcat and then open a web browser with the default home page loaded (http://localhost:8080/helloWS/index.html).
You can also run the example application using Maven and Jetty. Open a command window and navigate to the project's root folder (for example: c:\restful_projects\helloWS\"). Then type mvn clean and then mvn jetty:run. Once you see [INFO] Started Jetty Server in the command window, open a web browser and go to this URL: http://localhost:8080/helloWS/index.html). To stop the Jetty server just type ctrl-c in the command window.
You can also view the example application on Google AppEngine/Java.
Examining The Example Code
There is only one Java class file in this project: HelloResource.java. This class file uses annotations to map HTTP protocols such as get and post to methods. This example is a simple web service where the methods return plain text. Of course Jersey RESTful web services are capable of producing (and consuming) many different kinds of mime media types including XML, JSON, and HTML.
The first annotation in the source file is @Path.
@Path("/hello")
public class HelloResource {
...
}
On this web page from Sun's RESTful Web Services Developer's Guide is a handy chart that explains some of the annotations defined by JAX-RS and implemented by Jersey. The @Path is used to specify the URL for this Java class. So if I want to call any of the methods in this class as a web service over HTTP, my url needs to have /hello. For example: http://localhost:8080/helloWS/services/hello. Note that in the web.xml I mapped the web service classes to the url-pattern /services/* so that is why the URI includes services.
The class next defines a simple method that returns the String "Hello"
@GET
@Produces("text/plain")
public String getMessage() {
// Return plain text
return "Hello";
}//end method getMessage
This method has two annotations @GET and @Produces. The @GET annotation specifies that this method will respond to get requests. So this method will be executed if the URL is http://localhost:8080/helloWS/services/hello.
The @Produces annotation is used to specify the mime media type that this method will send back to the browser. So when the user calls this method using the URL http://localhost:8080/helloWS/services/hello the method will send the word "Hello" back as the response.
The next two methods show how a web service can use parameters. The first method has additional annotations: @Path and @PathParam
@GET
@Path("{username}")
@Produces("text/plain")
public String getMessage(@PathParam("username") String userName) {
return "Hello " + userName;
}//end overloaded method getMessage
The @Path annotation is used here to specify that this method will respond to URLs with an additional path that is to be treated as the value for the method's parameter userName. So calling the URL http://localhost:8080/helloWS/services/hello/Bruce will cause this method to execute and the path value "Bruce" will become the value passed to the method's userName parameter. This method will then return "Hello Bruce" to the browser.
The last method in the HelloResource.java class is used to consume the form parameter sent as a post to the class.
@POST
@Consumes("application/x-www-form-urlencoded")
@Produces("text/plain")
public String postMessage(@FormParam("name") String name) {
return "Hello " + name;
}//end method postMessage
The annotation @POST specifies that this method will process HTTP post requests. The @Consumes annotation is used to specify the mime media type that this method can process. In this example, I specified that this method is used to consume form encoded data. In the index.html file you can view the form that calls this service.
<form method="post" action="services/hello">
<p>Name: <input type="text" name="name" /></p>
<p><input type="submit" name="submit" value="Submit" /></p>
</form>
Note the name value for the text input field, which is "name." This matches the @FormParam annotation in the postMessage method. Whatever value the user types into this text field will be used as the value for the method's name parameter. This method will then return "Hello " and the name value.
Deploment Descriptor
To configure Jersey and your RESTful web services you must add following to the web.xml file.
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>name.brucephillips.hellows.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
The param-value of name.brucephillips.hellows.resources tells Jersey to look in that package for classes annotated to act as RESTful web services. There are alternative ways to setup the RESTful web services in web.xml. See the section headed: Deploying a RESTful Web service on this web page.
Summary
This article has been a quick introduction to creating and running a simple RESTful web service using Jersey, Eclipse, Maven, and Tomcat. In future articles, I'll explore more complicated examples of RESTful web services including one that consumes and returns XML that contains a collection of nodes representing Java objects and is called from within the browser using Ajax.
Jersey and RESTful web services provide a powerful but relatively simple-to-use methodology for Java developers to create dynamic web applications. Once you understand the annotations that Jersey implements (@Path, @GET, etc) it's not difficult to turn a POJO into a RESTful web service. Trying to create a similar capability using Java servlets or Struts 2 ActionSupport classes is more difficult and convoluted.
References
- Example Application - Archived Eclipse - Maven Project
- View Example Application on Google AppEngine/Java
- RESTful Web Service, wikipedia
- RESTful Web Services: The Basics IBM developerWorks
- JAX-RS, the Java API for RESTful web services
- jsr311-api 1.0 API
- Jersey, Sun's Reference Implementation for JAX-RS
- RESTful Web Services Developer's Guide, Sun MicroSystems
- REST: Jersey configuration on Tomcat, Surya Suravarapu's Blog
- JAX-RS as the basis of a DRY web framework, James Strachan's Blog
- Using JAX-RS (Jersey) to build a JPA/JAXB-backed JSON REST API, java rants blog
- Hacking Jersey/JAX-RS to run RESTful web services on Google AppEngine/Java, LQD Journal
One of the few articles describing developing RESTful WS using Eclipse and Tomcat.
1: Install maven (used "q" version, or its decendent)
2: Delete the reference to the jre in the project build
3: add the jdk in windows > preference > install
4: add that reference as a library in the project build
5: have maven down load, right click on the "m" in the project and click "use"
I'm new to server-side REST development, but you made it clear for me. Thanks!