Earthly Powers
- All
- Fast Infoset
- General
- Java
- REST
Jersey 0.7 is released

We have just released version 0.7 of Jersey (see the stable download directory). This aligns with the 0.7 release of the JAX-RS API and the March editors draft.
This version will be available soon from the Glassfish Update Centre.
Phew! this was a tough one. There were many additions and clarifications to the API. The email statistics for the 311 EG list looks like a climb profile (maybe up Alpe D'Huez like Lance if you squint your eyes).
So most of our time was spent on API aspects.
However, Jakub got some good feedback on the JSON support and fixed related bugs.
Martin Grotzke has been working on improving Spring, and in general IoC integration, support in a branch. The plan is to make this part of the 0.8 distribution, and hopefully we will manage to solve some difficult issues w.r.t. mixing IoC-based and Jersey-based components when injecting parameters of constructor/methods that Jersey is responsible for invoking.
I finally managed to play around with the latest JavaRebel and SDK and formalize the reloading of the Jersey runtime when resource classes are added, modified or removed.
As a nice bonus Jean Francois kindly visited Grenoble for a day and we hashed out a Grizzly/Comet/Jersey prototype. I think we may have a very interesting and simple way of integrating Comet functionality with resource classes. Jean Francois has created a branch and we will work from that to progress such support. Unfortunately i did not have time to move to Grizzly 1.7.3 but i am very excited about prospects for 1.8.0 and an asynchronous client-side API based on Grizzly as i can make good use of that with the Jersey client-side API.
Now it is time to prepare for JavaOne. Marc and I have a technical session on JAX-RS @ Tuesday 12:10. Jakub and I have a BOF on Jersey @ Tuesday 20:30. I should be around for the GF unconference on the Sunday before, and will be partially around for the CommunityOne event on the Monday before (Marc and I have to prepare for the session so we cannot attend for the whole day).
I am thinking of two possible dates for the 0.8 release, 20th June or the 25th of July. The reason being is the Jazoon conference is at the end of June, we need to relax a bit (i go on holiday a week after Jazoon for 2 weeks), and there are more API changes to implement although not of Alpe D'Huez proportions.
Posted at 01:49PM Apr 18, 2008 by Paul Sandoz in REST | Comments[4]
JavaRebel and Jersey: Take 2
Since i last played with JavaRebel it has been through one or more updates and now has an SDK. It is also been a while since i blogged, from the graph generated by Marc you should be able to determine why.
Finally i managed to get some time to revisit JavaRebel (many thanks to Jevgeni Kabanov for updating me on the progress of JavaRebel and sending pointers to relevant information). This entry explains how to dynamically reload the Jersey deployed web application in response to callbacks from JavaRebel when in detects changes to class files. Because Jersey caches runtime information about classes, for performance reasons, it needs to be informed to update information about classes that have changed. So adding a new HTTP method or a new resource class can be detected.
The code at the end of the blog shows a complete example that can work with the latest build of Jersey 0.7, JavaRebel 1.1 M3 and the JavaRebel SDK 1.1 M3.
To connect JavaRebel to Jersey we need to implement two interfaces, the JavaRebel inteterface ReloadListener and the Jersey interface ContainerNotifier:
01 private static class Reloader implements ContainerNotifier,
02 ReloadListener {
03 private final List<ContainerListener> ls;
04
05 private final ClasspathResourceConfig rc;
06
07 public Reloader(ClasspathResourceConfig rc) {
08 ls = new ArrayList<ContainerListener>();
09 this.rc = rc;
10 }
11
12 public void addListener(ContainerListener l) {
13 ls.add(l);
14 }
15
16 public void reloaded(Class arg0) {
17 rc.reload();
18 for (ContainerListener l : ls) {
19 l.onReload();
20 }
21 }
22 }
The method reloaded on line 16 will get invoked every time JavaRebel detects a change to a Java class. The method addListener will get called by a Jersey container that wants to listen to container-based notifications. All containers shipped with Jersey will add a ContainerListener to a ContainerNotifier (if one is present, see later). When the reloaded method is invoked the class path is rescanned for classes then each listener registered with the container notifier will notified by an invocation of the onReload method (see line 19).
Next the ReloadListener and the ContainerNotifier need to be registered:
01 ClasspathResourceConfig rc = new ClasspathResourceConfig();
02 Reloader r = new Reloader(rc);
03
04 rc.getProperties().put(
05 ResourceConfig.PROPERTY_CONTAINER_NOTIFIER, r);
06 ReloaderFactory.getInstance().addReloadListener(r);
07
08 HttpServer s = HttpServerFactory.create("http://localhost:9999/",
09 ContainerFactory.createContainer(HttpHandler.class, rc));
10 s.start();
Lines 1 and 2 create the resource configuration (that scans class paths) and creates the reloader as previously shown. Lines 4 and 5 register the ContainerNotifier with Jersey by adding a property to the resource configuration. Line 6 registers the ReloadListener with JavaRebel. Finally lines 8, 9 and 10 start the Light Weight HTTP Server.
So if we configure to use JavaRebal, build and run the app, then change the code of the simple web application, recompile while still running, then Jersey will update accordingly.
I think the general concept works OK but it does require some finessing as currently it could be described as a rather brutish approach. A reload will occur for every class that has changed so Jersey will perform unnecessary reloads. I don't know how JavaRebel works but it may be useful to provide reloading within an a scope of "startReload" and "endReload". Furthermore Jersey needs to know about classes that have been removed and not just those that have been modified or added (i have not tested what JavaRebel does when classes are removed). On the Jersey side i think we can refine this to support add/update or deletion of classes. For resource classes this is probably fairly easy. For provider classes it is a little more work.
I could imagine such reloading capability might be useful not just for rapid development but for dynamic deployment of additional root resource classes as and when they are required.
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.ws.rest.api.container.ContainerFactory;
import com.sun.ws.rest.api.container.httpserver.HttpServerFactory;
import com.sun.ws.rest.api.core.ClasspathResourceConfig;
import com.sun.ws.rest.api.core.ResourceConfig;
import com.sun.ws.rest.spi.container.ContainerListener;
import com.sun.ws.rest.spi.container.ContainerNotifier;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import org.zeroturnaround.javarebel.ReloadListener;
import org.zeroturnaround.javarebel.ReloaderFactory;
public class Main {
@Path("/{id}")
public static class RebelResource {
@GET
public String getOne(@PathParam("id") int id) {
return Integer.toString(id) + "x";
}
}
private static class Reloader implements ContainerNotifier,
ReloadListener {
private final List<ContainerListener> ls;
private final ClasspathResourceConfig rc;
public Reloader(ClasspathResourceConfig rc) {
ls = new ArrayList<ContainerListener>();
this.rc = rc;
}
public void addListener(ContainerListener l) {
ls.add(l);
}
public void reloaded(Class arg0) {
rc.reload();
for (ContainerListener l : ls) {
l.onReload();
}
}
}
public static void main(String[] args) throws Exception {
ClasspathResourceConfig rc = new ClasspathResourceConfig();
Reloader r = new Reloader(rc);
rc.getProperties().put(
ResourceConfig.PROPERTY_CONTAINER_NOTIFIER, r);
ReloaderFactory.getInstance().addReloadListener(r);
HttpServer s = HttpServerFactory.create("http://localhost:9999/",
ContainerFactory.createContainer(HttpHandler.class, rc));
s.start();
try {
System.in.read();
} finally {
s.stop(0);
}
}
}
Posted at 06:07PM Apr 16, 2008 by Paul Sandoz in REST | Comments[0]
Jersey 0.6 is released

We have just released version 0.6 of Jersey (see the stable download directory). This aligns with the 0.6 release of the JAX-RS API and the latest editors draft.
This version will be available soon from the Glassfish Update Centre and as part of the NetBeans RESTful Web service plugin from the NetBeans Beta Update Centre.
We managed to achieve most things we highlighted in the schedule (more on the missing bits later).
Jakub added improved JSON un/marshaling to JAXB so one can produce JSON from JAXB beans that is much easier to consume by applications like jMaki (see the jMakiBackend example in the Jersey distribution). (I wonder if it is applicable to applications like GWT ?).
We improved on the work Marc did integrating Jersey with IoC containers, like Spring or Guice. Most developer-based things in Jersey are now components that defer to a "component provider" for instantiation and injection. This enables the life-cycle of resource classes to be independent of the IoC container. A developer on the Jersey users list has already experimented with Guice. There are some friction points that still need to be resolved: the main one being constructors where the IoC framework chooses the constructor but only knows about some constructor parameters and Jersey knows about others (especially request-based parameters like those from the request URI).
It is now very easy to register implementations of MessageBodyReader/Writer (the same underlying mechanism scanning for resource classes is reused). Marc and I show (here and here) how such readers/writers can be used with Abdera to create simple Atom-based services.
I promoted the client API used for Jersey unit testing to a public API of Jersey, see here (note that the class ResourceProxy has now been renamed to WebResource as suggested by Stefan Tilkov). This API focuses on the uniform interface constraint and i have found it very productive when writing unit tests. Some of the existing APIs focus on the lower-level request/response which as a consequence makes them more clunky to use. It also borrows from ease of use aspects of JAX-RS and the runtime, especially the message body readers/writers.
Finally i managed to put into code a very simple SPI for plugging in template processors and enabling a flexible model view controller approach. Essentially a resource class can return a template name and a model. The template name gets resolved to a template file in the class path that can be processed by a registered template processor that in turn processes the template with the given the model. I plan to blog about this in more detail later. The Bookstore example in the Jersey distribution provides an example of implicit views using JSPs. A developer on the user list has enabled Freemarker templates in a couple of lines of code and has experimental XSTL translations with JAXB beans (see this thread, which also attempts to explain the difference between implicit and explicit views).
The two areas where we did not make as much progress were adding servlet-based unit tests and evaluating a transition to using Maven.
However, recently on the users list there were requests about using Jetty with Jersey. That gave me just enough information to work things out fairly quickly so now i think we can get good unit tests in place for Jersey's servlet support and increase the code coverage percentages.
As for Maven, we just ran out of time. I believe it is likely to be a significant overhaul of the Jersey build process to transition to Maven and i have heard some Maven-hell stories that make me pause before diving in... so if there are any Maven experts out there with some free time of their hands and would like to help just drop me an email.
In terms of what's next:
- align with 0.7 of the JAX-RS API and fill in all those missing little gaps (this may be a lot of work);
- improve the scope of the JSON support (namely supporting XML attributes);
- refine the MVC and template processor support to manage content types and language;
- (if time permits) experiment with Grizzly and comet;
- (if time permits) provide as part of the Jersey distribution component providers for Guice and Spring. This may be popular judging from the comments we have received; and
- (if time permits) give some more Scala and Groovy TLC to Jersey;
As usual feedback and participation are most welcome, just send email to the users list and/or log issues.
Posted at 02:21PM Mar 07, 2008 by Paul Sandoz in REST | Comments[13]
Jersey Client API
Yesterday i finished refactoring the Jersey Client API and sprinkling it with some JavaDoc. This API was originally being used for Jersey unit testing but i think it is applicable in the larger context of a general RESTful client API.
With some HTTP-based client APIs you have to do a lot of crufty work to make even the simplest request and process a response. In addition they do not really capture the concept of resources and the uniform interface. I think this may be one reason why client-side code generation for creating a 'proxy' to a HTTP-based service is more prevalent than i think it should be. With this client API it is very easy to produce requests and consume responses with resources and the uniform interface at the fore of the API. Hopefully if you play with this API you will see how easy it is to use and why code-generation (and in general relying statically on specific server-side artifacts) is of less importance in this respect.
At the end of this blog is a complete example showing the basic features of the client-side API. This works with the latest Jersey 0.6 build. It contains a resource, called PropertiesResource, a message body reader/writer for reading and writing properties, and some client code in the Main.run method. When this code is executed it should complete successfully with no exception thrown. The example tests simple create, read, update and delete of properties where the server is in control of the property names and the client chooses the property values.
Let's go through the statements of the Main.run method.
Setting up the client:
ClientConfig cc = new DefaultClientConfig();
cc.getProviderClasses().add(PropertiesProvider.class);
Client c = Client.create(cc);
The client can utilize message body readers and writers just like the server-side (in addition to IoC frameworks). I have yet to implement the client-scanning parts so for now it is necessary to explicitly register readers and writers.
Create a resource proxy to the properties resource:
ResourceProxy pResource = c.proxy("http://localhost:9998/");Now we can start calling methods on the resource proxy:
Properties p = pResource.get(Properties.class);
assertTrue(p.size() == 0);
A GET request should return a Properties instance that has no properties. Notice how the HTTP method is used a bit like RMI but since the interface is uniform it never varies for standard HTTP-based resources. Like the server-side the client side can easily avail of Java types for representations.
Creating a new property resource:
ClientResponse cr = pResource.
type("text/plain").
post(ClientResponse.class, "some stuff");
assertTrue(cr.getStatus() == 201);
A POST method is called on the properties resource. The builder pattern is used to set the content type of the request (it is possible for the client to specify what is acceptable using the accept method) and the post method is invoked with the requested return type and the request entity (a String instance). The status code of the response should be 201 (Created). Notice that the client can choose to get all the response information or the representation previously shown for the GET request. The same methods are used as it is the return type that specifies such behavior.
Verify the created property resource:
ResourceProxy vResource = c.proxy(cr.getLocation());
String content = vResource.get(String.class);
assertTrue("some stuff".equals(content));
The response to the POST request (if successful) will contain the location to the newly created property resource. This can be used to create a new resource proxy. A get method is called on that resource proxy and it should return the same information that was POSTed.
Verify the contents of the created property resource are also present in the properties resource:
p = pResource.get(Properties.class);
assertTrue(p.size() == 1);
assertTrue(p.contains("some stuff"));
Delete the created resource:
try {
vResource.delete();
} catch (UniformInterfaceException e) {
assertTrue(false);
}The DELETE method on the property resource is invoked. In this case the client does not send anything and does not request a response. If something other than a successful response occurs an exception will be thrown.
Verify that the property resource has been deleted:
try {
content = vResource.get(String.class);
} catch (UniformInterfaceException e) {
assertTrue(e.getResponse().getStatus() == 404);
}In this case we expect an exception to be thrown. The ClientResponse can be obtained from the exception to check the status code, which should be 404 (Not Found). But we can also do it like this if we wish:
cr = vResource.get(ClientResponse.class);
assertTrue(cr.getStatus() == 404);
So it is possible to verify the status code explicitly or work under the assumption that success is the norm and errors are the exception.
Hopefully that gives you a flavor of how to use the API from a resource and uniform interface perspective. Given the recent blogs on Jersey and Abdera (see here and here) it should be easy to apply Abdera on the Jersey client side as it was on the server side.
If you want you can still build client requests independently and pass them to the Client instance. You can also add filters for say performing authentication. There is a lot that still can be done. For example, a client requesting a CreatedResponse could verify the status code and location header and throw an exception if it does not conform. Asynchronous requests may be possible by the client requesting say Future<String> or Future<ClientResponse>. I already have a feature request to add request/response progress listeners. Since services may be clients too there is lots of opportunity for such clients to share resources with the server making things more efficient and scalable. So much to do! If you would like to help out just contact me :-)
import com.sun.net.httpserver.HttpServer;
import com.sun.ws.rest.api.client.Client;
import com.sun.ws.rest.api.client.ClientResponse;
import com.sun.ws.rest.api.client.ResourceProxy;
import com.sun.ws.rest.api.client.UniformInterfaceException;
import com.sun.ws.rest.api.client.config.ClientConfig;
import com.sun.ws.rest.api.client.config.DefaultClientConfig;
import com.sun.ws.rest.api.container.httpserver.HttpServerFactory;
import com.sun.ws.rest.spi.resource.Singleton;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.Properties;
import java.util.UUID;
import javax.ws.rs.ConsumeMime;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.ProduceMime;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.HttpContext;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
public class Main {
@ProduceMime("text/plain")
@Provider
public static class PropertiesProvider implements
MessageBodyWriter<Properties>,
MessageBodyReader<Properties> {
public void writeTo(Properties p, MediaType mediaType,
MultivaluedMap<String, Object> headers, OutputStream out)
throws IOException {
p.store(out, null);
}
public boolean isWriteable(Class<?> type) {
return Properties.class.isAssignableFrom(type);
}
public long getSize(Properties p) {
return -1;
}
public boolean isReadable(Class<?> type) {
return Properties.class.isAssignableFrom(type);
}
public Properties readFrom(Class<Properties> type, MediaType mediaType,
MultivaluedMap<String, String> headers, InputStream in)
throws IOException {
Properties p = new Properties();
p.load(in);
return p;
}
}
@Path("/")
@ProduceMime("text/plain")
@ConsumeMime("text/plain")
@Singleton
public static class PropertiesResource {
@HttpContext UriInfo uriInfo;
Properties p = new Properties();
@GET public Properties get() {
return p;
}
@POST public Response post(String in) {
String id = UUID.randomUUID().toString();
p.setProperty(id, in);
URI u = uriInfo.getAbsolutePathBuilder().path(id).build();
return Response.created(u).build();
}
@Path("{id}") @GET public synchronized String getContent(
@PathParam("id") String id) {
String content = p.getProperty(id);
if (content == null) throw new WebApplicationException(404);
return content;
}
@Path("{id}") @PUT public synchronized void updateContent(
@PathParam("id") String id) {
String content = p.getProperty(id);
if (content == null) throw new WebApplicationException(404);
p.setProperty(id, content);
}
@Path("{id}") @DELETE public synchronized void deleteContent(
@PathParam("id") String id) {
String content = p.getProperty(id);
if (content == null) throw new WebApplicationException(404);
p.remove(id);
}
}
public static void run() throws Exception {
// Create the client
ClientConfig cc = new DefaultClientConfig();
// Include the properties provider
cc.getProviderClasses().add(PropertiesProvider.class);
Client c = Client.create(cc);
// Create the resource proxy to the resource
ResourceProxy pResource = c.proxy("http://localhost:9998/");
// Get the current properties and verify it is empty
Properties p = pResource.get(Properties.class);
assertTrue(p.size() == 0);
// Create a new property
ClientResponse cr = pResource.
type("text/plain").
post(ClientResponse.class, "some stuff");
assertTrue(cr.getStatus() == 201);
// Verify the created resource
ResourceProxy vResource = c.proxy(cr.getLocation());
String content = vResource.get(String.class);
assertTrue("some stuff".equals(content));
// Get the current properties and verify the contents
p = pResource.get(Properties.class);
assertTrue(p.size() == 1);
assertTrue(p.contains("some stuff"));
// Delete the created resource
try {
vResource.delete();
} catch (UniformInterfaceException e) {
// This will occur when a status >= 300 occurs
assertTrue(false);
}
// Verify resource is deleted
try {
content = vResource.get(String.class);
} catch (UniformInterfaceException e) {
// This will occur when a status >= 300 occurs
assertTrue(e.getResponse().getStatus() == 404);
}
// Verify resource is deleted using ClientResponse
cr = vResource.get(ClientResponse.class);
assertTrue(cr.getStatus() == 404);
// Verify properties resource contains no properties
p = pResource.get(Properties.class);
assertTrue(p.size() == 0);
}
private static void assertTrue(boolean v) {
if (v == false) throw new RuntimeException();
}
public static void main(String[] args) throws Exception {
HttpServer server = HttpServerFactory.create("http://localhost:9998/");
server.start();
try {
run();
} finally {
server.stop(0);
}
}
}
Posted at 03:20PM Feb 08, 2008 by Paul Sandoz in REST | Comments[8]
Jersey and Abdera with a twist of JSON
Marc recently blogged on integrating Jersey with Abdera. Marc shows how easy it is to integrate, especially if using the latest Jersey 0.6 builds (see the comments) as there is no need to use the messy and error prone META-INF/services for registration of message body readers/writes.
I am going to extend Marc's example to add a twist of JSON to the mix. James shows here how to use Abdera with JSON (in the larger context of mapping between Atom documents encoded in XML and JSON). If you want to play with this code you will need to use the latest Jersey 0.6 build.
Lets refactor the AbderaSupport class to be as follows:
public abstract class BaseAbderaSupport implements
MessageBodyWriter<Object>,
MessageBodyReader<Object> {
private final static Abdera abdera = new Abdera();
public static Abdera getAbdera() {
return abdera;
}public long getSize(Object arg0) {
return -1;
}public boolean isWriteable(Class<?> type) {
return Feed.class.isAssignableFrom(type) ||
Entry.class.isAssignableFrom(type);
}public void writeTo(Object feedOrEntry, MediaType mediaType)
MultivaluedMap<String, Object> headers,
OutputStream outputStream) throws IOException {
if (feedOrEntry instanceof Feed) {
Feed feed = (Feed) feedOrEntry;
write(feed.getDocument(), outputStream);
} else {
Entry entry = (Entry) feedOrEntry;
write(entry.getDocument(), outputStream);
}
}public boolean isReadable(Class<?> type) {
return Feed.class.isAssignableFrom(type) ||
Entry.class.isAssignableFrom(type);
}public Object readFrom(Class<Object> feedOrEntry, MediaType mediaType,
MultivaluedMap<String, String> headers,
InputStream inputStream) throws IOException {
Document<Element> doc = read(inputStream);
Element el = doc.getRoot();
if (feedOrEntry.isAssignableFrom(el.getClass())) {
return el;
} else {
throw new IOException("Unexpected payload, expected " +
feedOrEntry.getName() +
", received " + el.getClass().getName());
}
}protected abstract void write(Document<? extends Base> doc,
OutputStream outputStream) throws IOException;
protected abstract Document<Element> read(InputStream inputStream)
throws IOException;
}
Notice the protected abstract methods at the end. Then lets extend this base class for XML support:
@Provider
@ProduceMime("application/atom+xml")
@ConsumeMime("application/atom+xml")
public class XMLAbderaSupport extends BaseAbderaSupport {
protected void write(Document<? extends Base> doc,
OutputStream outputStream) throws IOException {
doc.writeTo(outputStream);
}
protected Document<Element> read(InputStream inputStream) throws IOException {
return getAbdera().getParser().parse(inputStream);
}
}
and extend for JSON support:
@Provider
@ProduceMime("application/json")
@ConsumeMime("application/json")
public class JSONAbderaSupport extends BaseAbderaSupport {
protected void write(Document<? extends Base> doc,
OutputStream outputStream) throws IOException {
Writer w = getAbdera().getWriterFactory().getWriter("json");
doc.writeTo(w, outputStream);
}
protected Document<Element> read(InputStream inputStream) throws IOException {
Parser p = getAbdera().getParserFactory().getParser("json");
return p.parse(inputStream);
}
}
Notice that the JSONAbderaSupport class uses the "application/json" media type.
Now lets create a very simple resource that returns an empty Atom feed:
@ProduceMime({"application/atom+xml", "application/json"})
@Path("myfeed")
public class FeedResource {
@HttpContext
private UriInfo uriInfo;
@GET
public Feed getFeed() {
Feed f = BaseAbderaSupport.getAbdera().getFactory().newFeed();
f.setTitle("TITLE");
URI feedLink = uriInfo.getRequestUri();
f.addLink(feedLink.toString(),"self");
return f;
}
}
Notice that the feed resource declares that it produces the "application/atom+xml" and the "application/json" media types.
Penultimately lets deploy all this using the light weight HTTP server:
HttpServer server = HttpServerFactory.create("http://localhost:9998/");
server.start();
Notice that there is no need to explicitly reference the classes XMLAbderaSupport, JSONAbderaSupport and FeedResource. By default they are found automatically by scanning the Java classes files in the java.class.path for the appropriate annotations.
Finally lets test the feed resource using curl (i have formatted the output):
curl -v -H "Accept: application/atom+xml" http://localhost:9998/myfeed
* About to connect() to localhost port 9998
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 9998
> GET /myfeed HTTP/1.1
> User-Agent: curl/7.15.5 (i386-pc-solaris2.11) libcurl/7.15.5
OpenSSL/0.9.8a zlib/1.2.3 libidn/0.6.8
> Host: localhost:9998
> Accept: application/atom+xml
>
< HTTP/1.1 200 OK
< Date: Thu, 07 Feb 2008 10:48:35 GMT
< Content-type: application/atom+xml
< Transfer-encoding: chunked
* Connection #0 to host localhost left intact
* Closing connection #0
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title type="text">TITLE</title>
<link href="http://localhost:9998/myfeed" rel="self" />
</feed>curl -v -H "Accept: application/json" http://localhost:9998/myfeed
* About to connect() to localhost port 9998
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 9998
> GET /myfeed HTTP/1.1
> User-Agent: curl/7.15.5 (i386-pc-solaris2.11) libcurl/7.15.5
OpenSSL/0.9.8a zlib/1.2.3 libidn/0.6.8
> Host: localhost:9998
> Accept: application/json
>
< HTTP/1.1 200 OK
< Date: Thu, 07 Feb 2008 10:49:02 GMT
< Content-type: application/json
< Transfer-encoding: chunked
* Connection #0 to host localhost left intact
* Closing connection #0
{
"contributors":[],
"title":"TITLE","categories":[],
"entries":[],
"authors":[],
"links":[
{
"href":"http://localhost:9998/myfeed",
"rel":"self"
}]
}
In less than an hour of playing around and writing this blog I have XML and JSON support for servicing Atom documents. Of course it helps that Abdera made it easy to integrate. My first impressions of playing around with Jersey and Abdera are that they are very complimentary for building Atom-based services.
Posted at 12:08PM Feb 07, 2008 by Paul Sandoz in REST | Comments[3]
JavaOne and Jazoon
We submitted a technical session on JAX-RS and a BOF on Jersey to JavaOne and both have been accepted.
In terms of the technical session our current thinking is we would like to describe the REST style (grounded in the Resource Oriented Architecture terminology), how it connects to the JAX-RS API, and how you code to that API in a series of logical steps (for example the Resource Oriented Architecture properties) to build an example. I think this would be better than lots of talk (cue hand waving) followed by a 5 to 10 minute demo. Intermixing these three things is a tricky balancing act but i think its worth the effort to better communicate about JAX-RS. We need to choose an example, if you have any ideas on what you would like to see, write a comment or send me some email.
In terms of the BOF i deliberately made the abstract "loose" and would like to drive the content based on feedback before or at the BOF. We can come up with some pre-prepared slides on the Jersey architecture, additional features, JAX-RS, and some demos but i would really like things driven by what developers want to see. So again if you have any ideas/requests write a comment or send me some email.
I have also been invited to present at Jazoon08 (and very much enjoyed Jazoon07 last year). I suspect we are going to reuse a lot of material that was prepared for JavaOne :-) but we will endeavor to improve it based on feedback we receive.
Posted at 01:56PM Feb 05, 2008 by Paul Sandoz in REST | Comments[0]
Integrating Jersey and Spring: Take 2
Marc previously described how to integrate Spring with Jersey 0.4 for the instantiation of root resources. This was an great first step but it fell short in a couple of areas:
- there was some initialization code that could not be performed at initialization stage;
- it was necessary to annotate (or specify the default provider for) all resources with a Spring specific life-cycle annotation, thus it was not possible to write 'vanilla' resources for use with Spring; and
- this was only applicable to root resource classes. Jersey has other components, such as instances of MessageBodyReader/Writer, and it would be useful if those components could also be Spring-enabled.
I have spent this week unifing the instantiation of components (in addition to removing the requirement of META-INF/services for registration, it is all dynamic like for root resource classes). Instantiation of any component managed in Jersey is deferred to a ComponentProvider. By default Jersey provides a basic implementation but it is possible to provide an application-specific implementation for say Spring. Jersey will then adapt that implementation so that Spring-registered and non-Spring-registered components can be instantiated.
(All code referenced below only works with the latest build of Jersey.)
I am still pondering the best way to declare an application-specific ComponentProvider but for now i am experimenting specifically with a Spring aware Servlet. Jersey ships with a servlet that can be extended to configure the WebApplication, which makes it very easy to extend for Spring support. Below is the code for the SpringServlet:
public class SpringServlet extends ServletContainer {
private static class SpringComponentProvider implements ComponentProvider {
private ApplicationContext springContext;
SpringComponentProvider(ApplicationContext springContext) {
this.springContext = springContext;
}
private String getBeanName(Class c) {
String names[] = springContext.getBeanNamesForType(c);
if (names.length == 0) {
return null;
} else if (names.length > 1) {
throw new RuntimeException("Multiple configured beans for "
+ c.getName());
}
return names[0];
}
public Object getInstance(Scope scope, Class c)
throws InstantiationException, IllegalAccessException {
String beanName = getBeanName(c);
if (beanName == null) return null;
if (scope == Scope.WebApplication &&
springContext.isSingleton(beanName)) {
return springContext.getBean(beanName, c);
} else if (scope == Scope.ApplicationDefined &&
springContext.isPrototype(beanName) &&
!springContext.isSingleton(beanName)) {
return springContext.getBean(beanName, c);
} else {
return null;
}
}
public Object getInstance(Scope scope, Constructor contructor,
Object[] parameters)
throws InstantiationException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
return null;
}
public void inject(Object instance) {
}
};
@Override
protected void initiate(ResourceConfig rc, WebApplication wa) {
ApplicationContext springContext = WebApplicationContextUtils.
getRequiredWebApplicationContext(getServletContext());
wa.initiate(rc, new SpringComponentProvider(springContext));
}
}Notice that SpringServlet extends ServletContainer and the initiate method is overridden. This method creates an ApplicationContext and then initiates the WebApplication by passing in an instance of the static inner class SpringComponentProvider. This class implements ComponentProvider and the getInstance method will attempt to obtain a Spring bean that is present and matches the requested scope, if so then the bean instance is returned otherwise null is returned. (Note that the getInstance method with a Constructor type parameter is not implemented, this is because we have not determined how to support constructors with Spring beans).
The SpringServlet can be used in a web.xml as follows:
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
<listener>
<description>Spring listener that initializes the ApplicationContext in ServletContext</description>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>Jersey Spring</servlet-name>
<servlet-class>test.spring.SpringServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Spring</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Then i can create two root resource classes. The first, SingletonResource, uses the Jersey supplied singleton life-cycle:
@Path("singleton")
@Singleton
public class SingletonResource {
private String name;
private int uses = 0;
private synchronized int getCount() {
return ++uses;
}
public SingletonResource() {
name = "unset";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@GET
@ProduceMime("text/plain")
public String getDescription() {
return "Name: " + getName() + ", Uses: " + Integer.toString(getCount());
}
}
and the second, PerRequestResource, uses the per-request life-cycle:
@Path("request")
public class PerRequestResource {
private String name;
private int uses = 0;
private synchronized int getCount() {
return ++uses;
}
public PerRequestResource() {
name = "unset";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@GET
@ProduceMime("text/plain")
public String getDescription() {
return "Name: " + getName() + ", Uses: " + Integer.toString(getCount());
}
}
The root resources are almost identical except that the former is annotated with @Singleton, but they should return different output (as shown later).
Then i can create the Spring applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans">
<bean id="bean1" scope="singleton" class="test.spring.SingletonResource">
<property name="name" value="Mr. Singleton Bean"/>
</bean>
<bean id="bean2" scope="prototype" class="test.spring.PerRequestResource">
<property name="name" value="Mr. PerRequest Bean"/>
</bean>
</beans>
Where the root resource classes are registered (with the appropriate scope) and a property is specified for each.
Then i can deploy and test using curl (the '>' character is my shell prompt):
> curl http://localhost:8080/SpringResourceWebApp/singleton ; echo
Name: Mr. Singleton Bean, Uses: 1
> curl http://localhost:8080/SpringResourceWebApp/request ; echo
Name: Mr. PerRequest Bean, Uses: 1
>
> curl http://localhost:8080/SpringResourceWebApp/singleton ; echo
Name: Mr. Singleton Bean, Uses: 2
> curl http://localhost:8080/SpringResourceWebApp/request ; echo
Name: Mr. PerRequest Bean, Uses: 1
>
> curl http://localhost:8080/SpringResourceWebApp/singleton ; echo
Name: Mr. Singleton Bean, Uses: 3
> curl http://localhost:8080/SpringResourceWebApp/request ; echo
Name: Mr. PerRequest Bean, Uses: 1
Notice that the response to the URI containing the 'singleton' path segment returns the 'Mr. Singleton Bean' property as specified in the applicationContext.xml, and similarly the URI containing the 'request' path segment returns the 'Mr. PerRequest Bean' property. Also notice that the Uses value for the singleton-based URI increments for each request where as the one for the request-based URI does not. It works!
Having to edit applicationContext.xml is something i would prefer to avoid and instead utilize some Spring specific annotations. The ComponentProvider interface could probably do with some tweaks to make things more efficient for per-request life-cycle. But in general it seems to work reasonably well and i am sure the same concepts for Spring integration would apply to Guice.
Posted at 01:49PM Feb 01, 2008 by Paul Sandoz in REST | Comments[39]
Jersey 0.5 is released

We have just released version 0.5 of Jersey (see the stable download directory). This aligns with the 0.5 release of the JAX-RS API and the latest editors draft.
This version will be available soon from the Glassfish Update Centre and as part of the NetBeans RESTful Web service plugin from the NetBeans Beta Update Centre.
This release has improved the deployment and configuration process. The annoying pre-compile step is gone, which means no need to modify build configuration scripts. It is now a very simple process. For example, using Grizzly:
SelectorThread s = GrizzlyServerFactory.create("http://locahost:9090/");
Or the Light Weight HTTP server:
HttpServer s = HttpServerFactory.create("http://localhost:9090/");
s.start();
Or using standard elements in a web.xml file for Web applications deployed using Glassfish (or other compliant Servlet containers):
<servlet>
<servlet-name>Resources</servlet-name>
<servlet-class>com.sun.ws.rest.spi.container.servlet.ServletContainer</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Resources</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Underneath the covers, thanks to Frank's ASM code, Jersey will efficiently scan Java class files present in the java.class.path for Grizzly and the Light Weight HTTP server or in the WEB-INF/classes and WEB-INF/lib for Web applications. This mechanism is extensible so it is possible to plug in a different discovery mechanism. Jersey also comes with an implementation to scan Java class files given a set of package names, which can be configured for a Web application as follows:
<servlet>
<servlet-name>Resources</servlet-name>
<servlet-class>com.sun.ws.rest.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.ws.rest.config.property.resourceConfigClass</param-name>
<param-value>com.sun.ws.rest.api.core.PackagesResourceConfig</param-value>
</init-param>
<init-param>
<param-name>com.sun.ws.rest.config.property.packages</param-name>
<param-value>com.acme.myresources;com.foo.myresources</param-value>
</init-param>
</servlet>
A recent comment on Marc's blog entry about Jersey Spring integration showed how this could be achieved for Spring for resource classes present in the Spring context.
WADL generation is improved and is generated dynamically (no configuration is required), as described here and here.
The URI dispatching architecture was completely re-written is much more flexible and pluggable. So we can easily adapt to changing requirements in the JAX-RS API in addition to Jersey specific requirements. For example, we integrated Frank's efficient URI matching algorithm as a component that kicks in when there are more than 8 URI path templates to be matched (that number can probably be reduced, but I was being conservative!). I am sure there is more innovation and performance improvements we can do here.
The Grizzly support was over-hauled and we moved to the most recent version, 1.7, thanks to JFA's help.
The examples have been converted to use NetBeans 6.0.
The next release, 0.6, is scheduled for March 7th, as show here, which lists a number of areas we plan to work on. There are three main goals for the 0.6 release:
a high-level client-side API;
a better component and life-cycle model for all JAX-RS related components; and
model, view controller support with a pluggable template rendering.
I think these goals align well with feedback we have been getting about JAX-RS and Jersey. They are rather ambitious but we will try our best to get it all done!
As usual feedback and participation is most welcome, just send email to the users list and/or log issues.
Posted at 09:50AM Jan 18, 2008 by Paul Sandoz in REST | Comments[6]
JavaRebel and Jersey
I have been playing with JavaRebel (thanks for the tip Kohsuke!) and Jersey. JavaRebel:
reloads changes to Java classes on-the-fly without redeploy or restart including new methods and fields. It is a generic solution that works for standalone Java applications as well as application servers
I opened the HelloWorld example provided in the Jersey distribution and modified the run.jvmargs property in the nbproject/project.properties file to be:
run.jvmargs=-noverify -javaagent:<dir>/javarebel.jar
ran the project and verified with curl the response to a GET request.
Then i modified the String returned by the HTTP GET method of the HelloWorldResource recompiled the project and verified the response to the GET request had changed. (I wish NetBeans had an automatic compile option.)
It is also possible to integrate with Glassfish (although i have not tried it). Add the following snippet of XML as a child of the <java-config> element in a domain.xml:
<jvm-options>-noverify</jvm-options>
<jvm-options>-javaagent:<dir>/javarebel.jar</jvm-options>
A very nice and easy integration. Clever stuff! I wonder how it is done...
Unfortunately it is not possible to modify the annotations, method signatures, add new methods, or add new resource classes. Jersey creates, for performance reasons, a runtime model of a resource so it does not have to analyze the annotations using Java reflection every time. Jersey has no way of knowing if a resource class has been created, modified or deleted. (I suppose it is the same for any framework that caches information about classes, for example JAXB.)
If there was a way to detect changes i think it would be easy to modify Jersey to update its runtime model accordingly (an API for listening to such changes seems useful independently of JavaRebel). And then it would make a rather nice rapid development platform for Jersey development.
Posted at 02:12PM Jan 04, 2008 by Paul Sandoz in REST | Comments[7]
Jersey using Grizzly 1.7
One might be laboring under the misconception that Grizzly should be hibernating at this time, but no, Grizzly 1.7 is wide awake. Just updated Jersey to use 1.7, and the 0.5 release will use this version.
Next up... try to figure out how to connect Grizzly to Jersey for 100 (Continue) and Comet support. I believe it should be possible, although the mechanism to do this in Java using anonymous inner classes might not be pretty, much better in Scala :-)
I also wonder if it may be possible to utilize Grizzly's UDP support (how about someone getting reliable Multicast integrated into Grizzly?) to get Jersey working over UDP i know that is not HTTP on the wire but it could be interesting to experiment with granular publish/subscribe like what the Microsoft's RESTful robotics framework does.
Posted at 12:06PM Dec 21, 2007 by Paul Sandoz in REST | Comments[0]
JavaPolis
Last week i spoke about JAX-RS and Jersey at JavaPolis. The slides are here. Initially i was a bit worried that there were too many slides but i managed to present in 50 minutes with 10 minutes spare that was fully taken up with questions.
Rather embarrassingly i drew a complete blank (and ignored my own general advice on REST that i was imparting!) on one question related to managing users if user information should not be stored as part of session state. Thankfully a JRuby guy in the audience, Ola Bini, came to my rescue and described what Rails does!
A user can have state and thus be a resource that is accessible using a user specific URI. HTTP messages should be stateless so the information declaring the user of each request is supplied by the authentication HTTP request headers. Sounds easy but as i understand it the current Java APIs tend to encourage the developer to use HTTP session state. The area of HTTP authentication and the Java APIs is one that I need to do more research on and then write a blog on the subject as penance!
I enjoyed Martin Odersky's talk on Scala. However, i suspect this is not the right way to present Scala to those who have never seen and/or tried it before. One of my biggest gripes about Scala was the lack of documentation, looks like that has changed with the new Programing in Scala book that is available as an early edition.
Josh Bloch changed his talk and instead presented on the 'Closures Controversy". He was very convincing and i could be persuaded by a sugary syntactical improvement for anonymous inner classes if only because such classes are real pain to write. But Neal provides some counter balance in this blog. Still i don't think the counter balance is enough. Before the conference i was of the opinion that we should leave the Java language alone, not bolt on stuff for which there is an "impedance mismatch", and instead focus resources into improving JVM support for language features, like closures, in Scala, Groozy, JRuby etc. If anything the conference reinforced my opinion.
The OSGi presentation was interesting. Seems like more application servers are adopting the OSGi model and it seems a genuinely useful framework for development, management and versioning of software components for both small and large scale software systems. After this presentation i had some interesting discussions on the topic of the Java language and OSGi. I may well be leaning to the opinion that the work on Java modules and super packages is not necessary and instead the JVM should have an OSGi implementation embedded in it.
Posted at 03:17PM Dec 19, 2007 by Paul Sandoz in REST | Comments[2]
Dynamic WADL generation in Jersey
Current stable versions of Jersey require an awkward tool time step to identify the set of root resource classes and then generate a WADL document, from that set, that is accessible from the Web application.
For the next release, 0.5, everything will be dynamic. And we have just finished adding dynamic WADL support to the trunk. So the same URI, <base URI>/application.wadl, to access the WADL of the Web application is supported but no tool-time configuration is required. There is a runtime requirement that the JAXB jars be in the class path, if not then WADL support is turned off but the Web application will still work.
In addition there is experimental support for GETing the WADL of a specific resource. At deployment the runtime only knows about root resource classes but a Web application can dynamically return other resources. This allows a client to GET WADL for such resources enabling the client to "WADL" through the resources :-) I like this approach, it fits more closely with the view of WADL as hypermedia and using WADL in a much more loosely coupled way rather than a way to describe the whole Web application.
Currently WADL is obtained by a client performing a GET request on a URI and setting the Accept header to include the media type "application/vnd.sun.wadl+xml". I am not sure i like this approach as it can interfere with application specific GET methods (it is implemented so application specific GET methods take priority, thus WADL may not always be returned).
Two other approaches may be more appropriate:
- Return WADL as the representation of HTTP OPTIONS response. The OPTIONS method is automatically supported to return the allowed HTTP methods in the Allow response header.
- Return WADL using a sub-resource, say "/application.wadl".
Posted at 01:03PM Dec 12, 2007 by Paul Sandoz in REST | Comments[0]
A Grizzly Jersey
No not some blog to get the hackles raised on the anti-fur league...
With much help from the very responsive JFA we have upgraded the Grizzly support in Jersey to the latest jars, and we will be moving to version 1.7 as soon as it is released. As part of this upgrade unit tests have been added to ensure quality support.
Now it is really easy to create a Grizzly Jersey Adapter, deploy root resources to it, create a SelectorThread and then start the endpoint:
SelectorThread s = GrizzlyServerFactory.
create("http://locahost:9090");
That is it!
Posted at 10:54AM Dec 05, 2007 by Paul Sandoz in REST | Comments[0]
Using Jersey and Scala's features for HTTP preconditions
Jersey has a way to plug in processing of Java methods that are HTTP methods (annotated with a @HttpMethod). A resource method dispatch provider analyzes a method signature (of a resource class) and if the signature is suitable returns a request dispatcher that knows how to transform a HTTP request to instances of the method parameter types and transform an instance of the returned type to a HTTP response.
(Note that this plug-in mechanism is not currently exposed as a documented SPI
and it is mostly internal to Jersey. However, the plan is to expose this as documented functionality. Also what is presented below is only possible in the latest builds of Jersey so this is all still very much experimental.)
This can make for interesting ways to define and process HTTP methods especially using features of other JVM-compatible languages, like Scala, that support closures.
A RESTful framework like Jersey has some areas where it would be useful for a developer to return some meta-data and a function where by the runtime analyzes the meta-data and from that data the runtime decides if the function should be called or not. Such areas are:
- precondition support, an HTTP method returns meta-data consisting of an entity tag and/or a last modified date, and a function to be called if preconditions are met. The runtime checks the meta-data against the associated HTTP request headers and if preconditions are not met a 304 (Not Modified) or a 412 (Precondition Failed) response is returned (and the function is not called).
- variant selection, an HTTP method that may produce one or more representations consisting of one or more media types, languages, character sets and encodings can return a 'sparse' variant matrix and a function to be called with the variant selected by the runtime according to what the client accepts.
I strongly suspect that 100 (Continue) responses can also fall into area and perhaps more generally Comet-based support, for example, using Scala's actors.
I hacked together a proof of concept resource method dispatch provider written in Scala to support preconditions. So i can write a simple Scala resource class as follows:
import PartialResponse._
@UriTemplate("/")
class MethodService {
@ProduceMime(Array("text/plain"))
@HttpMethod
def get() = partialResponse("1234") {
"RESPONSE"
}
}
(Obviously this example is contrived since the entity tag is hard coded).
The partialResponse is a method imported on the object PartialResponse and it takes as the first parameter a string that is the entity tag "1234" and as the second parameter a function (essentially a closure) that is the block of code that returns the string "RESPONSE".
I deployed this class using the Light Weight HTTP server:
HttpServerFactory.create("http://localhost:9998/method").start()
(Thanks to a recent feature change Jersey now automatically picks up resource classes by scanning the Java class files, by default, using the java class path.)
And performed a GET request using curl that returns a 304 (Not Modified) response:
> GET /method/ HTTP/1.1
> Host: localhost:9998
> Accept: */*
> If-None-Match: "1234"
>
< HTTP/1.1 304 Not Modified
< Content-length: 0
< Etag: "1234"
So as you can see in this case preconditions are not being met: essentially the client already has the latest state of the resource "/method".
The code for PartialResponse is as follows:
object PartialResponse {
def partialResponse(t: String)(body: => Object):
PartialResponse = {
val response = new PartialResponse {
def entityTag() : String = t
def respond() : Object = body
}
response
}
}
trait PartialResponse {
def entityTag() : String
def respond() : Object
}
The partialResponse method creates a anonymous instance of the trait PartialResponse and sets the methods entityTag and respond accordingly.
The code for the resource method dispatch provider and request dispatcher is presented at the end of this blog and below i highlight the relevant code that performs the precondition calculation:
01 val pr = method.invoke(resource, null).
02 asInstanceOf[PartialResponse]
03
04 val t = new EntityTag(pr.entityTag)
05 var r = request.evaluate(t)
06 if (r == null) {
07 val ar = pr.respond()
08
09 val mediaType = getAcceptableMediaType(request);
10 r = Response.Builder.representation(ar, mediaType).
11 tag(t).build();
12 }
13 response.setResponse(r);
Line 1 and 2 invokes the Java method that is the HTTP method (here it is assumed the method takes no parameters) and the response is cast to a Partial