JAX-RS Services with Jersey

In today’s “Web Services” world, two of the common implementations are SOAP based or JAX-RS based services.
Today, I want to briefly discuss how to implement services in JAX-RS using the Jersey implementation.

REST is based on the idea that calls made to an application should have very specific purposes (ie. retrieving data, adding data, deleting data, or updating data).
REST calls should not try accomplish more than one at a time and JAX-RS follows this design pattern. The 4 HTTP methods: GET, PUT, DELETE, POST align with this.

Exposing a JAX-RS service is fairly simple. First, you add the Jersey Servlet to your web.xml:

  <servlet>
    <servlet-name>Jersey REST Service</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>somePackage</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>

Note, you should configure the to something that makes sense. For the example above, any URL under /rest/ will be processed by this servlet.

Second, you need to annotate a class with the @Path(“abcdefg”) attribute to configure the URL pattern the class will handle:

	//Sets the path to base URL + /hello
	@Path("/hello")
	public class JerseyRESTService {
		...
	}

This would make the JerseyRESTService class respond to all requests in this pattern: /rest/hello/. Note, you can further refine the URL pattern on each individual method in the class.

Finally, we need to implement our functionality within the class.
Retrieving data should be done with the GET method. You can return almost any type of data you wish. The response format is configured using the @Produces annotation.

	@GET
	@Produces(MediaType.TEXT_PLAIN)
	public String sayPlainTextHello() {
		return "Hello Jersey";
	}

This method only responds to a HTTP GET request at the URL pattern, /rest/hello. It returns a text result. If want XML you can set @Produces(MediaType.TEXT_XML). If you want HTML, you can set @Produces(MediaType.TEXT_HTML).

Also, if you want the method to return more than one type of data, you can add them as a list, to the @Produces annotation:

	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})

When this happens, your request must specify the data type you are requesting in the “Accept” header.

Adding data should be done with the PUT method. It must consume whatever data is being added via the @Consumes annotation:

	@PUT
	@Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML})
	public Response saveCar(JAXBElement<Car> c){
		Car myCar = c.getValue();
				
		Response res = Response.ok("<response>200</response>").type("text/xml").build();
				
		return res;
	}

Car is an object I defined with 3 properties (manuf, model, color). To invoke this method, I would need to make a HTTP PUT request to /rest/hello, with an XML body like this:

<car>
	<color>Red</color>
	<manuf>Tesla</manuf>
	<model>Model S</model>
</car>

The XML will be serialized using JAXB and converted to a Car object for easy access.

Removing data should be done with the DELETE method. If you need to tell the method what to delete, use the @Consumes annotation.

	@DELETE
	@Consumes(MediaType.APPLICATION_XML)
	public void deleteCar(JAXBElement<Car> c){
		Car myCar = c.getValue();
		System.out.println(myCar.getColor());
	}

This example is similar to the @PUT example. It will respond to a HTTP DELETE request at /rest/hello and consume an XML body that matches the Car object.

Updating data should be done with the POST method. I won’t go into that because it should be self explanatory at this point.

One last thing I want to mention is how to pass data via a URL request instead of part of the HTTP body. You do that through the @PathParam annotation:

	@GET
	@Produces(MediaType.TEXT_XML)
	@Path("{name}")
	public String sayXMLHello(@PathParam("name") String name) {
		return "<?xml version=\"1.0\"?>" + "<hello> Hello " + name + "</hello>";
	}

This method would respond to GET requests at /rest/hello. However, it will expect a single parameter after the hello. That parameter will be inserted into the @PathParam attribute, name. A request in this format /rest/hello/george would print “Hello george”. This is useful for looking up objects by ID.

You can also deploy JAX-RS services to respond to Form Data that is posted by a browser UI. Its very similar to the @PathParam example, but instead, you use @FormParam.

Next article will show an example …