Links: Table of Contents | Single HTML

Chapter 6. Declarative Hyperlinking

Table of Contents

6.1. Links in Representations
6.2. Binding Template Parameters
6.3. Conditional Link Injection
6.4. Link Headers
6.5. Configuration

RESTful APIs must be hypertext-driven. JAX-RS currently offers UriBuilder to simplify URI creation but Jersey adds an additional annotation-based alternative that is described here.

6.1. Links in Representations

Links are added to representations using the @Ref annotation on entity class fields. The Jersey runtime is responsible for injecting the appropriate URI into the field prior to serialization by a message body writer. E.g. consider the following resource and entity classes:

@Path("widgets")
public class WidgetsResource {
  @GET
  public Widgets get() {
    return new Widgets();
  }
}
        
public class Widgets {
  @Ref(resource=WidgetsResource.class)
  URI u;
}

After a call to WidgetsResource#get, the Jersey runtime will inject the value "/context/widgets"[1] into the returned Widgets instance. If an absolute URI is desired instead of an absolute path then the annotation can be changed to @Ref(resource=WidgetsResource.class, style=ABSOLUTE).

The above usage works nicely when there's already a URI template on a class that you want to reuse. If there's no such template available then you can use a literal value instead of a reference. E.g. the following is equivalent to the earlier example: @Ref(value="widgets", style=ABSOLUTE).

6.2. Binding Template Parameters

Referenced or literal templates may contain parameters. Two forms of parameters are supported:

  • URI template parameters, e.g. widgets/{id} where {id} represents a variable part of the URI.

  • EL expressions, e.g. widgets/${instance.id} where ${instance.id} is an EL expression.

Parameter values can be extracted from three implicit beans:

instance

Represents the instance of the class that contains the annotated field.

entity

Represents the entity class instance returned by the resource method.

resource

Represents the resource class instance that returned the entity.

By default URI template parameter values are extracted from the implicit instance bean, i.e. the following two annotations are equivalent:

@Ref("widgets/{id}")
@Ref("widgets/${instance.id}")

The source for URI template parameter values can be changed using the @Binding annotation, E.g. the following two annotations are equivalent:

@Ref(value="widgets/{id}", bindings={
  @Binding(name="id" value="${resource.id}"}
)
@Ref("widgets/${resource.id}")

6.3. Conditional Link Injection

Link value injection can be made conditional by use of the condition property. The value of this property is a boolean EL expression and a link will only be injected if the condition expression evaluates to true. E.g.:

@Ref(value="widgets/${instance.id}/offers",
  condition="${instance.offers}")
URI offers;

In the above, a URI will only be injected into the offers field if the offers property of the instance is true.

6.4. Link Headers

HTTP Link headers can also be added to responses using annotations. Instead of annotating the fields of an entity class with @Ref, you instead annotate the entity class itself with @Link. E.g.:

@Link(
  value=@Ref("widgets/${resource.nextId}"),
  rel="next"
)

The above would insert a HTTP Link header into any response whose entity was thus annotated. The @Link annotation contains properties that map to the parameters of the HTTP Link header. The above specifies the link relation as next. All properties of the @Ref annotation may be used as described above.

Multiple link headers can be added by use of the @Links annotation which can contain multiple @Link annotations.

6.5. Configuration

Declarative hyperlinking support is provided in the form of a filter. First, the application must declare a dependency on the jersey-server-linking module:

<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-server-linking</artifactId>
  <version>${jersey-version}</version>
</dependency>

Second the filter needs to be installed in the application either programmatically by adding:

com.sun.jersey.server.linking.LinkFilter

to the list defined by:

com.sun.jersey.spi.container.ContainerResponseFilters

or using a web.xml init parameter:

<init-param>
  <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
  <param-value>com.sun.jersey.server.linking.LinkFilter</param-value>
</init-param>

See the jersey-server-linking-sample for more details.



[1] Where /context is the application deployment context.