Skip to main content

Declarative Hyperlinking in Jersey

Posted by mhadley on March 10, 2010 at 1:36 PM PST

One of the areas I'm keen to improve in the next version of JAX-RS is link creation. JAX-RS already offers UriBuilder but I think an annotation driven approach could save a lot of repetitive coding.

I've been experimenting with a couple of annotations that I think would be useful and I just checked in an experimental extension that partially implements what I have in mind. Suppose you have a resource like this:

@Path{"widgets"}
public class WidgetsResource {
  ...
}

and you want to include a URI to this resource in a representation. Using the new extension you can just annotate a field in your representation class like this:

@Link(resource=WidgetsResource.class)
URI link;

and then Jersey will build the appropriate URI and inject it into the representation before the representation is serialized by a message body writer.

If the URI template contains parameters, their values are obtained by looking for a bean property or field by the same name in the representation. E.g. consider the following representation class:

public class WidgetRepresentation {
  @Link("widgets/{widgetId}")
  URI link;
 
  String getWidgetId() {...}
}

After processing by the extension, if the getWidgetId method returned "abc123", the value of the link field would be /context/widgets/abc123 where context is the deployment context.

The optional style property of the @Link annotation can be used to select between absolute URIs, absolute path and relative path depending on requirements.

Using the Extension

In order to try out the extension you have to:

  • Declare a dependency on the new jersey-server-linking module which is available in Jersey trunk under the experimental directory.
  • Install the response filter in your application using an init-param in the web.xml like this:
    <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>
            <param-value>your application packages here</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
            <param-value>com.sun.jersey.server.linking.LinkFilter</param-value>
        </init-param>

        <load-on-startup>1</load-on-startup>
    </servlet>

Next Steps

The Javadoc of the @Link annotation describes a couple of things that I plan to implement next:

  • Support for the @Binding annotation already sketched out in the code. This will allow the values of template parameters to be pulled from alternate sources including differently named properties of the representation and resource.
  • Support for EL expressions in link templates. This will allow a little more expressivity for templates that don't already exist as values of @Path annotations.

Comments

Great stuff!

Nice work Marc! I'm liking it. I started a rather long reply and found comments come out as one big assed paragraph, so shot an email to the jersey lists instead :) http://n2.nabble.com/thoughts-on-Link-and-Marc-s-blog-post-td4715173.htm...