Table of Contents
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.
This API is currently under development and experimental so it is subject to change at any time.
To use Declarative Linking you need to add jersey-declarative-linking
module to your pom.xml
file:
<dependency> <groupId>org.glassfish.jersey.ext</groupId> <artifactId>jersey-declarative-linking</artifactId> <version>2.24.1</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.
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 toWidgetsResource#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)
.
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}")
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
.
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
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( @InjectLink(value="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.
By default, Jersey will try to recursively find all @InjectionLink
annotations in
the members of your object unless this member is annotated with @XmlTransient
.
But in some cases, you might want to control which member will be introspected regardless of the
@XmlTransient
annotation.
You can prevent Jersey to look into an object by adding @InjectLinkNoFollow
to a field.
@InjectLinkNoFollow Context context;
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);