February 18, 2010

Using Jersey to (un)marshall Java objects

When developing a REST API in Java, it is straightforward when you do that using Jersey. At least when implementing the server side. For instance, we can have the following methods to manage a Foo object:

@GET
@Path("{fooId}")
@Produces("application/xml")
public Foo getFoo(@PathParam("fooId") int fooId) {
return FooBean.getInstance().findFoo(fooId);
}

@GET
@Path("/list")
@Produces("application/xml")
public List<Foo> getFoos() {
return FooBean.getInstance().findAllFoos();
}

@PUT
@Produces("application/xml")
public Foo putFoo(@FormParam("name") String name, @FormParam("bar") String bar) {
Foo foo = new Foo();
foo.setName(name);
foo.setBar(bar);
return FooBean.getInstance().createFoo(foo);
}

@POST
@Path("/{fooId}")
@Produces("application/xml")
public Foo updateFoo(@PathParam("fooId") int fooId, @FormParam("name") String name, @FormParam("bar") String bar) {
Foo foo = FooBean.getInstance().findFoo(fooId);
if (foo != null) {
foo.setName(name);
foo.setBar(bar);
return FooBean.getInstance().updateFoo(foo);
}

return null;
}

@DELETE
@Path("/{fooId}")
public void deleteFoo(@PathParam("fooId") int fooId) {
FooBean.getInstance().deleteFoo(fooId);
}


The Foo class must be annotated with @XmlRootElement, otherwise Jersey won't know how to marshall the object into XML or JSON.

@XmlRootElement
public class Foo implements Serializable {
private int id;
private String name;
private String bar;
...
}


Recently I discovered that you can also use Jersey when developing client applications that make use of a REST API. The Jersey Client API, as it is called, can be used to easily produce and consume REST requests and responses. The code below shows a quick overview of how to call the methods listed above.

Client client = Client.create();

WebResource wr = client.resource("http://localhost:8080/jm/rest/foo");

// getting a single Foo object
Foo foo = wrGetFoo.path("/1").get(Foo.class);

// getting a list of Foo objects
List<Foo> foos = wr.path("/list").get(new GenericType<List<Foo>>() {});

// creating a Foo object
MultivaluedMap params = new MultivaluedMapImpl();
params.add("name", "Foo2");
params.add("bar", "bar2");
Foo foo2 = wr.put(Foo.class, params);

// updating a Foo object
params.clear();
params.add("name", "Foo2");
params.add("bar", "bar2updated");
foo2 = wr.path("/" + foo2.getId()).post(Foo.class, params);

// deleting a Foo object
wr.path("/" + foo2.getId()).delete();


As you can see, the methods on the WebResource class map perfectly with the HTTP methods generally used in a REST API: GET, POST, PUT and DELETE. You can download the sample project, jerseymarshall.zip, which contains two NetBeans projects: a web project for the server side and a plain java project for the client side.