Chapter 13. Declarative Hyperlinking
Prev |  | Next

Links: Table of Contents | Single HTML

# Chapter 13. Declarative Hyperlinking

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.

### Important

This API is currently under development and experimental so it is subject to change at any time.

## 13.1. Dependency

To use Declarative Linking you need to add `jersey-jersey.ent` module to your `pom.xml` file:

    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-declarative-linking</artifactId>
        <version>2.16</version>
    </dependency>

Additionaly you will need to add the following dependencies, if you are not deploying into a container that is already including them:

    <dependency>
        <groupId>javax.el</groupId>
        <artifactId>javax.el-api</artifactId>
        <version>2.2.4</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.web</groupId>
        <artifactId>javax-el</artifactId>
        <version>2.2.4</version>
    </dependency>

If you're not using Maven make sure to have all needed dependencies (see jersey-declarative-linking) on the classpath.

## 13.2. Links in Representations

Links are added to representations using the `@InjectLink` 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 {
        @InjectLink(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 `@InjectLink(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: `@InjectLink(value="widgets", style=ABSOLUTE)`.

## 13.3. 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:

    @InjectLink("widgets/{id}")

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

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

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

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

## 13.4. 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.:

    @InjectLink(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`.

## 13.5. List of Link Injection

You can inject multiple links into an array of a List collection type. E.g.:

    @InjectLinks({@InjectLink(resource=WidgetsResource.class, rel = "self")})
    List<Link> links

## 13.6. Link Headers

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

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

The above would insert a HTTP Link header into any response whose entity was thus annotated. The `@InjectLink` 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 `@InjectLink` annotation may be used as described above.

Multiple link headers can be added by use of the `@InjectLinks` annotation which can contain multiple `@InjectLink` annotations.

## 13.7. Configure and register

In order to add the Declarative Linking feature register DeclarativeLinkingFeature

Example 13.1. Creating JAX-RS application with Declarative Linking feature enabled.

    // Create JAX-RS application.
    final Application application = new ResourceConfig()
            .packages("org.glassfish.jersey.examples.linking")
            .register(DeclarativeLinkingFeature.class);

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

Prev |  | Next
Chapter 12. URIs and Links | Home | Chapter 14. Programmatic API for Building Resources