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, or fork it on Github

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>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, or fork it on Github

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.