Creating a simple Java RESTful service using Jersey and Maven
There has been a lot of interest in Resource Orientated Architecture (ROA) online which has resulted in an explosion of excellent libraries that make it simple to use this architectural style.
The example in this article uses Java, Maven and a JAX-RS library called Jersey to create a very simple orders system.
Our order consists of a reference number and a customer name. The system has three entry points:
- HTTP PUT to create an order
- HTTP GET to see the details of an order
- HTTP GET to see all the existing orders
Download the full source of this article here.
To make it simple to get it up and running I’ve added configuration for Jetty to run on port 9090. You can compile the source code and run a web server to use it by issuing this single Maven command:
mvn jetty:run
I recommend that you use curl to test your RESTful web services as it is easy to change the HTTP verb that you are using. You can manipulate the orders system using these curl commands.
# Add a new order for Bob with ID 1 curl -X PUT http://localhost:9090/orders-server/orders/1?customer_name=bob # Check the status of the order curl -X GET http://localhost:9090/orders-server/orders/1 # See all the orders in the system curl -X GET http://localhost:9090/orders-server/orders/list
Note: HTTP GET is the default verb used by curl, I’ve explicitly listed GET in the examples to make it clear which verb is in use.
The code
To use Jersey you need to add a servlet to your web.xml and create a resource implementation class.
web.xml
The WEB-INF/web.xml fragment sets up the Jersey Servlet with a parameter listing the package to search for RESTful classes.
<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>
<!-- Important bit -->
<param-value>com.joejag.code.orders.restservices</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
This reads any classes in the com.joejag.code.orders.restservices and looks for annotations declaring resources.
The Java class
On the implementation class you can see the @Path annotation on the class signature indicating the resource we are handling. This is used by Jersey to configure the URL used to interact with the resource.
Each method has a sub-path declared, an HTTP verb to respond from and the response type to produce. The method parameters are bound by using either part of the path (with @PathParam) or a separate query parameter (with @QueryParam).
package com.joejag.code.orders.restservices;
import java.util.Map;
import java.util.TreeMap;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
@Path("orders")
public class OrdersService
{
// Stores state simply in a static collection class.
private static Map<String, String> orders = new TreeMap<String, String>();
@Path("/{order}")
@PUT
@Produces("text/html")
public String create(@PathParam("order") String order,
@QueryParam("customer_name") String customerName)
{
orders.put(order, customerName);
return "Added order #" + order;
}
@Path("/{order}")
@GET
@Produces("text/html")
public String find(@PathParam("order") String order)
{
if (orders.containsKey(order))
return "<h2>Details on Order #" + order +
"</h2><p>Customer name: " + orders.get(order);
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
@Path("/list")
@GET
@Produces("text/html")
public String list()
{
String header = "<h2>All Orders</h2>\n";
header += "<ul>";
for (Map.Entry<String, String> order : orders.entrySet())
header += "\n<li>#" + order.getKey() + " for " + order.getValue() + "</li>";
header += "\n</ul>";
return header;
}
}
Download the full source of this article here.
Where to learn more
There are a number of great articles on how to develop JAX-RS REST applications. I recommend you start with the Jersey guide for Java applications:
If you are using Ruby then take a look at the wonderful Sinatra project.
TweetThanks Joe
Thanks for the post Joe, good maven/RS example…
thanks
thanks for providing a tutorial that works!
Very good tutorial thanks alot
great tutorial and very helpful addition of including the jetty settings for running within eclipse!
Very good, thanks a lot
Excellent tutorial. Keep up the good work!
Thanks Joe. Great job!!!
How have you created the project in eclipse? With the m2eclipse plugin or running the mvn eclipse:eclipse?
Excellent tutorial that makes it simple and clean with maven. Indeed i have a problem i can’t figure out : how to deal to get (a not null) ServletContext in the service ?
I ‘ve tried a lot of methods, i always get null context and hece cannot get back parameters that have been passed (init-param) for example).
Could you modify your code and add a dummy example of how to get back context params (jetty/tomcat compatible) ?
This would be very helpful.
Got it !
in the web.xml, simply :
THE_KEY
THE_VALUE
in the pom :
com.sun.jersey
jersey-grizzly2
1.9.1
javax.servlet
servlet-api
2.4
Next, the list function becomes :
@Path(“/list”)
@GET
@Produces(“text/html”)
public String list() {
ServletContext ctx = context;
String test = (String) ctx.getInitParameter(“THE_KEY”);
System.out.println(“Retrieved from context : “);
String header = “All Orders\n”;
header += “”;
for (Map.Entry order : orders.entrySet()) {
header += “\n#” + order.getKey() + ” for ” + order.getValue() + “”;
}
header += “\n”;
return header;
}
And this is it, it’s ok, the param is retrieved from the context when listing.
Thank you very much for your very useful and simple tutorial.
Best Regards,
Adrien
Ok Joe, this tutorial is very great

{12} Comments