|  | <?xml version="1.0" encoding="UTF-8"?> | 
|  | <!-- | 
|  |  | 
|  | Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved. | 
|  |  | 
|  | This program and the accompanying materials are made available under the | 
|  | terms of the Eclipse Public License v. 2.0, which is available at | 
|  | http://www.eclipse.org/legal/epl-2.0. | 
|  |  | 
|  | This Source Code may also be made available under the following Secondary | 
|  | Licenses when the conditions for such availability set forth in the | 
|  | Eclipse Public License v. 2.0 are satisfied: GNU General Public License, | 
|  | version 2 with the GNU Classpath Exception, which is available at | 
|  | https://www.gnu.org/software/classpath/license.html. | 
|  |  | 
|  | SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | 
|  |  | 
|  | --> | 
|  |  | 
|  | <!DOCTYPE chapter [<!ENTITY % ents SYSTEM "jersey.ent" > %ents; ]> | 
|  | <chapter xmlns="http://docbook.org/ns/docbook" | 
|  | version="5.0" | 
|  | xml:lang="en" | 
|  | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
|  | xmlns:xi="http://www.w3.org/2001/XInclude" | 
|  | xmlns:xlink="http://www.w3.org/1999/xlink" | 
|  | xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd | 
|  | http://www.w3.org/1999/xlink http://www.w3.org/1999/xlink.xsd" | 
|  | xml:id="declarative-linking"> | 
|  |  | 
|  | <title>Declarative Hyperlinking</title> | 
|  |  | 
|  | <para> | 
|  | <link xlink:href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven">RESTful APIs must be | 
|  | hypertext-driven</link>. JAX-RS currently offers &jaxrs.core.UriBuilder; to simplify URI | 
|  | creation but Jersey adds an additional annotation-based alternative that is described here. | 
|  | </para> | 
|  | <important> | 
|  | <para> | 
|  | This API is currently under development and experimental so it is subject to change at any time. | 
|  | </para> | 
|  | </important> | 
|  |  | 
|  | <section> | 
|  | <title>Dependency</title> | 
|  |  | 
|  | <para> | 
|  | To use Declarative Linking you need to add &lit.jersey-declarative-linking; module to your &lit.pom.xml; file: | 
|  |  | 
|  | <programlisting language="xml" linenumbering="unnumbered"><dependency> | 
|  | <groupId>org.glassfish.jersey.ext</groupId> | 
|  | <artifactId>jersey-declarative-linking</artifactId> | 
|  | <version>&version;</version> | 
|  | </dependency></programlisting> | 
|  |  | 
|  | Additionally you will need to add the following dependencies, if you are not deploying | 
|  | into a container that is already including them: | 
|  |  | 
|  | <programlisting language="xml" linenumbering="unnumbered"><dependency> | 
|  | <groupId>jakarta.el</groupId> | 
|  | <artifactId>jakarta.el-api</artifactId> | 
|  | <version>&jakarta.el.version;</version> | 
|  | </dependency></programlisting> | 
|  |  | 
|  | <programlisting language="xml" linenumbering="unnumbered"><dependency> | 
|  | <groupId>org.glassfish.web</groupId> | 
|  | <artifactId>jakarta.el</artifactId> | 
|  | <version>&jakarta.el-impl.version;</version> | 
|  | </dependency></programlisting> | 
|  |  | 
|  | If you're not using Maven make sure to have all needed dependencies (see &jersey.ext.declarative-linking.deps.link;) on | 
|  | the classpath. | 
|  | </para> | 
|  | </section> | 
|  |  | 
|  |  | 
|  | <section> | 
|  | <title>Links in Representations</title> | 
|  |  | 
|  | <para> | 
|  | Links are added to representations using the <literal>@InjectLink</literal> 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: | 
|  | </para> | 
|  |  | 
|  | <programlisting language="java">@Path("widgets") | 
|  | public class WidgetsResource { | 
|  | @GET | 
|  | public Widgets get() { | 
|  | return new Widgets(); | 
|  | } | 
|  | } | 
|  |  | 
|  | public class Widgets { | 
|  | @InjectLink(resource=WidgetsResource.class) | 
|  | URI u; | 
|  | }</programlisting> | 
|  |  | 
|  | <para> | 
|  | After a call to <literal>WidgetsResource#get</literal>, the Jersey runtime will inject the value | 
|  | <literal>"/context/widgets"</literal> | 
|  | <footnote> | 
|  | <para> | 
|  | Where <literal>/context</literal> is the application deployment context. | 
|  | </para> | 
|  | </footnote> | 
|  | into the returned <literal>Widgets</literal> instance. If an absolute URI is | 
|  | desired instead of an absolute path then the annotation can be changed to | 
|  | <literal>@InjectLink(resource=WidgetsResource.class, style=ABSOLUTE)</literal>. | 
|  | </para> | 
|  | <para> | 
|  | 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: | 
|  | <literal>@InjectLink(value="widgets", style=ABSOLUTE)</literal>. | 
|  | </para> | 
|  | </section> | 
|  |  | 
|  | <section> | 
|  | <title>List of Link Injection</title> | 
|  | <para> | 
|  | You can inject multiple links into an array or a List collection type. E.g.: | 
|  | <programlisting language="java">@InjectLinks({@InjectLink(resource=WidgetsResource.class, rel = "self")}) | 
|  | List<Link> links</programlisting> | 
|  |  | 
|  | The field doesn't need to be initialized. However, if it already contains a collection with manually created links, | 
|  | then it will merge those with the generated links into a new collection which then replaces the field value. | 
|  | </para> | 
|  | </section> | 
|  |  | 
|  | <section> | 
|  | <title>Links from Resources</title> | 
|  |  | 
|  | <para> | 
|  | As an alternative to defining the links in the entity class, they can also be defined in the resource classes by | 
|  | annotating the resource methods with <literal>@ProvideLink</literal>. This has the benefit, that the target | 
|  | method is already known and doesn't need to be referenced. Other than that it has the same parameters and behaviors | 
|  | as <literal>@InjectLink</literal>. The entity classes need to have a field annotated with | 
|  | <literal>@InjectLinks</literal>, which can be empty. | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | The <literal>@ProvideLink</literal> annotation can be repeated to add links to different entities using different | 
|  | options. Entities are defined via the <literal>value</literal> property. If the entities are similar in structure they | 
|  | can also be declared as an array. <literal>@ProvideLink</literal> also works with class hierarchies, e.g., contributions | 
|  | defined for a superclass will also be injected into the derived classes (interfaces are not supported). | 
|  |  | 
|  | <programlisting language="java">@ProvideLink(value = Order.class,rel = "self", | 
|  | bindings = @Binding(name = "orderId", value = "${instance.id}")) | 
|  | @ProvideLink(value = PaymentConfirmation.class, rel = "order", | 
|  | bindings = @Binding(name = "orderId", value = "${instance.orderId}")) | 
|  | @GET | 
|  | @Path("/{orderId}") | 
|  | public Response get(@PathParam("orderId") String orderId)</programlisting> | 
|  | </para> | 
|  | </section> | 
|  |  | 
|  | <section> | 
|  | <title>Binding Template Parameters</title> | 
|  |  | 
|  | <para> | 
|  | Referenced or literal templates may contain parameters. Two forms of parameters are | 
|  | supported: | 
|  | <itemizedlist> | 
|  | <listitem><para> | 
|  | URI template parameters, e.g. <literal>widgets/{id}</literal> where <literal>{id}</literal> represents | 
|  | a variable part of the URI. | 
|  | </para></listitem> | 
|  | <listitem><para> | 
|  | EL expressions, e.g. <literal>widgets/${instance.id}</literal> where <literal>${instance.id}</literal> | 
|  | is an EL expression. | 
|  | </para></listitem> | 
|  | </itemizedlist> | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | Parameter values can be extracted from three implicit beans: | 
|  | <variablelist> | 
|  | <varlistentry> | 
|  | <term> | 
|  | <literal>instance</literal> | 
|  | </term> | 
|  | <listitem> | 
|  | <para>Represents the instance of the class that contains the annotated field.</para> | 
|  | </listitem> | 
|  | </varlistentry> | 
|  | <varlistentry> | 
|  | <term> | 
|  | <literal>entity</literal> | 
|  | </term> | 
|  | <listitem> | 
|  | <para>Represents the entity class instance returned by the resource method.</para> | 
|  | </listitem> | 
|  | </varlistentry> | 
|  | <varlistentry> | 
|  | <term> | 
|  | <literal>resource</literal> | 
|  | </term> | 
|  | <listitem> | 
|  | <para>Represents the resource class instance that returned the entity.</para> | 
|  | </listitem> | 
|  | </varlistentry> | 
|  | </variablelist> | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | By default URI template parameter values are extracted from the implicit <literal>instance</literal> bean, | 
|  | i.e. the following two annotations are equivalent: | 
|  |  | 
|  | <programlisting language="java">@InjectLink("widgets/{id}") | 
|  |  | 
|  | @InjectLink("widgets/${instance.id}")</programlisting> | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | The source for URI template parameter values can be changed using the <literal>@Binding</literal> | 
|  | annotation, E.g. the following three annotations are equivalent: | 
|  | <programlisting language="java">@InjectLink(value="widgets/{id}", bindings={ | 
|  | @Binding(name="id" value="${resource.id}"} | 
|  | ) | 
|  |  | 
|  | @InjectLink(value="widgets/{value}", bindings={ | 
|  | @Binding("${resource.id}")}) | 
|  | @InjectLink("widgets/${resource.id}")</programlisting> | 
|  | </para> | 
|  |  | 
|  | </section> | 
|  |  | 
|  | <section> | 
|  | <title>Conditional Link Injection</title> | 
|  | <para> | 
|  | Link value injection can be made conditional by use of the <literal>condition</literal> 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.: | 
|  |  | 
|  | <programlisting language="java">@InjectLink(value="widgets/${instance.id}/offers", | 
|  | condition="${instance.offers}") | 
|  | URI offers;</programlisting> | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | In the above, a URI will only be injected into the <literal>offers</literal> field if the | 
|  | <literal>offers</literal> property of the instance is <literal>true</literal>. | 
|  | </para> | 
|  | </section> | 
|  |  | 
|  | <section> | 
|  | <title>Link Headers</title> | 
|  | <para> | 
|  | <link xlink:href="http://tools.ietf.org/html/rfc5988#section-5">HTTP Link headers</link> can also be added | 
|  | to responses using annotations. Instead of annotating the fields of an entity class with | 
|  | <literal>@InjectLink</literal>, you instead annotate the entity class itself with | 
|  | <literal>@InjectLinks</literal>. E.g.: | 
|  | <programlisting language="java">@InjectLinks( | 
|  | @InjectLink(value="widgets/${resource.nextId}", rel="next") | 
|  | )</programlisting> | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | The above would insert a HTTP Link header into any response whose entity was thus annotated. | 
|  | The <literal>@InjectLink</literal> annotation contains properties that map to the parameters | 
|  | of the HTTP Link header. The above specifies the link relation as <literal>next</literal>. | 
|  | All properties of the <literal>@InjectLink</literal> annotation may be used as described above. | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | Multiple link headers can be added by use of the <literal>@InjectLinks</literal> annotation | 
|  | which can contain multiple <literal>@InjectLink</literal> annotations. | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  | Resource links via <literal>@ProvideLink</literal> are currently not supported for link headers. | 
|  | </para> | 
|  | </section> | 
|  |  | 
|  | <section> | 
|  | <title>Prevent Recursive Injection</title> | 
|  | <para> | 
|  | By default, Jersey will try to recursively find all <literal>@InjectionLink</literal> annotations in | 
|  | the members of your object unless this member is annotated with <literal>@XmlTransient</literal>. | 
|  |  | 
|  | But in some cases, you might want to control which member will be introspected regardless of the | 
|  | <literal>@XmlTransient</literal> annotation. | 
|  |  | 
|  | You can prevent Jersey to look into an object by adding <literal>@InjectLinkNoFollow</literal> to a field. | 
|  |  | 
|  | <programlisting language="java">@InjectLinkNoFollow | 
|  | Context context;</programlisting> | 
|  | </para> | 
|  | </section> | 
|  |  | 
|  |  | 
|  | <section> | 
|  | <title>Meta-annotation support</title> | 
|  | <para> | 
|  | The <literal>@ProvideLink</literal> annotation can be used as a meta-annotation, i.e., annotating your own annotation. | 
|  | This enables you to create custom annotations to reuse <literal>@ProvideLink</literal> configurations instead of | 
|  | copy pasting them on each method. There is a special marker class <literal>ProvideLink.InheritFromAnnotation</literal> | 
|  | that can be used in place of the actual entity class, this indicates that the <literal>Class<?> value()</literal> | 
|  | from the custom annotation should be used instead. | 
|  |  | 
|  | Repeated annotations are currently unsupported for this feature. Also the  <literal>Class<?> value()</literal> | 
|  | method must return a single class and not an array of classes. | 
|  | </para> | 
|  |  | 
|  | <para> | 
|  |  | 
|  | Here is an example (getter/setter omitted for brevity) of how a meta annotation can be used. | 
|  | The example app uses a <literal>Page</literal> class as a base class for all entities that contain paged data. | 
|  |  | 
|  | <programlisting language="java">public class Page { | 
|  | private int number; | 
|  |  | 
|  | private int size; | 
|  |  | 
|  | private boolean isPreviousPageAvailable; | 
|  |  | 
|  | private boolean isNextPageAvailable; | 
|  |  | 
|  | @InjectLinks | 
|  | private List<Link> links; | 
|  | }</programlisting> | 
|  |  | 
|  | Instead of duplicating the <literal>@ProvideLink</literal> annotations for the  next and previous links on every | 
|  | method, we create the following <literal>@PageLinks</literal> annotation. | 
|  |  | 
|  | <programlisting language="java">@ProvideLink(value = ProvideLink.InheritFromAnnotation.class, rel = "next", | 
|  | bindings = { | 
|  | @Binding(name = "page", value = "${instance.number + 1}"), | 
|  | @Binding(name = "size", value = "${instance.size}"), | 
|  | }, condition = "${instance.nextPageAvailable}") | 
|  | @ProvideLink(value = ProvideLink.InheritFromAnnotation.class, rel = "prev", | 
|  | bindings = { | 
|  | @Binding(name = "page", value = "${instance.number - 1}"), | 
|  | @Binding(name = "size", value = "${instance.size}"), | 
|  | }, condition = "${instance.previousPageAvailable}") | 
|  | @Target({ElementType.METHOD}) | 
|  | @Retention(RetentionPolicy.RUNTIME) | 
|  | @Documented | 
|  | public @interface PageLinks { | 
|  | Class<?> value(); | 
|  | }</programlisting> | 
|  |  | 
|  | The annotation can the then be used on the resource methods with the actual entity class as <literal>value</literal>. | 
|  |  | 
|  | <programlisting language="java">@PageLinks(OrderPage.class) | 
|  | @GET | 
|  | public Response list(@QueryParam("page") @DefaultValue("0") int page, | 
|  | @QueryParam("size") @DefaultValue("20") int size)</programlisting> | 
|  |  | 
|  | The entity just extends from <literal>Page</literal> and declares its content. It is necessary to use distinct classes | 
|  | instead of just a generic page to have a unique target for <literal>@ProvideLink</literal>, otherwise every method | 
|  | annotated with <literal>@ProvideLink(value=Page.class)</literal> would contribute to the entity. | 
|  |  | 
|  | <programlisting language="java">public class OrderPage extends Page { | 
|  | private List<Order> orders; | 
|  | }</programlisting> | 
|  | </para> | 
|  | </section> | 
|  |  | 
|  | <section> | 
|  | <title>Configure and register</title> | 
|  |  | 
|  | <para> | 
|  | In order to add the Declarative Linking feature register &jersey.linking.DeclarativeLinkingFeature; | 
|  |  | 
|  | <example> | 
|  | <title>Creating JAX-RS application with Declarative Linking feature enabled.</title> | 
|  |  | 
|  | <programlisting language="java">// Create JAX-RS application. | 
|  | final Application application = new ResourceConfig() | 
|  | .packages("org.glassfish.jersey.examples.linking") | 
|  | .register(DeclarativeLinkingFeature.class);</programlisting> | 
|  | </example> | 
|  | </para> | 
|  | </section> | 
|  | </chapter> |