33
44 DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
55
6- Copyright (c) 2010-2015 Oracle and/or its affiliates. All rights reserved.
6+ Copyright (c) 2010-2017 Oracle and/or its affiliates. All rights reserved.
77
88 The contents of this file are subject to the terms of either the GNU
99 General Public License Version 2 only ("GPL") or the Common Development
7676 < version>&version;< /version>
7777< /dependency> </programlisting >
7878
79- Additionaly you will need to add the following dependencies, if you are not deploying
79+ Additionally you will need to add the following dependencies, if you are not deploying
8080 into a container that is already including them:
8181
8282 <programlisting language =" xml" linenumbering =" unnumbered" >< dependency>
@@ -140,6 +140,45 @@ public class Widgets {
140140 </para >
141141 </section >
142142
143+ <section >
144+ <title >List of Link Injection</title >
145+ <para >
146+ You can inject multiple links into an array or a List collection type. E.g.:
147+ <programlisting language =" java" >@InjectLinks({@InjectLink(resource=WidgetsResource.class, rel = "self")})
148+ List< Link> links</programlisting >
149+
150+ The field doesn't need to be initialized. However, if it already contains a collection with manually created links,
151+ then it will merge those with the generated links into a new collection which then replaces the field value.
152+ </para >
153+ </section >
154+
155+ <section >
156+ <title >Links from Resources</title >
157+
158+ <para >
159+ As an alternative to defining the links in the entity class, they can also be defined in the resource classes by
160+ annotating the resource methods with <literal >@ProvideLink</literal >. This has the benefit, that the target
161+ method is already known and doesn't need to be referenced. Other than that it has the same parameters and behaviors
162+ as <literal >@InjectLink</literal >. The entity classes need to have a field annotated with
163+ <literal >@InjectLinks</literal >, which can be empty.
164+ </para >
165+
166+ <para >
167+ The <literal >@ProvideLink</literal > annotation can be repeated to add links to different entities using different
168+ options. Entities are defined via the <literal >value</literal > property. If the entities are similar in structure they
169+ can also declared as an array. <literal >@ProvideLink</literal > also works with class hierarchies, e.g., contributions
170+ defined for a superclass will also be injected into the derived classes (interfaces are not supported).
171+
172+ <programlisting language =" java" >@ProvideLink(value = Order.class,rel = "self",
173+ bindings = @Binding(name = "orderId", value = "${instance.id}"))
174+ @ProvideLink(value = PaymentConfirmation.class, rel = "order",
175+ bindings = @Binding(name = "orderId", value = "${instance.orderId}"))
176+ @GET
177+ @Path("/{orderId}")
178+ public Response get(@PathParam("orderId") String orderId)</programlisting >
179+ </para >
180+ </section >
181+
143182 <section >
144183 <title >Binding Template Parameters</title >
145184
@@ -229,15 +268,6 @@ URI offers;</programlisting>
229268 </para >
230269 </section >
231270
232- <section >
233- <title >List of Link Injection</title >
234- <para >
235- You can inject multiple links into an array of a List collection type. E.g.:
236- <programlisting language =" java" >@InjectLinks({@InjectLink(resource=WidgetsResource.class, rel = "self")})
237- List< Link> links</programlisting >
238- </para >
239- </section >
240-
241271 <section >
242272 <title >Link Headers</title >
243273 <para >
@@ -246,7 +276,7 @@ List<Link> links</programlisting>
246276 <literal >@InjectLink</literal >, you instead annotate the entity class itself with
247277 <literal >@InjectLinks</literal >. E.g.:
248278 <programlisting language =" java" >@InjectLinks(
249- @InjectLink(value="widgets/${resource.nextId}", rel="next")
279+ @InjectLink(value="widgets/${resource.nextId}", rel="next")
250280)</programlisting >
251281 </para >
252282
@@ -261,23 +291,94 @@ List<Link> links</programlisting>
261291 Multiple link headers can be added by use of the <literal >@InjectLinks</literal > annotation
262292 which can contain multiple <literal >@InjectLink</literal > annotations.
263293 </para >
264- </section >
294+
295+ <para >
296+ Resource links via <literal >@ProvideLink</literal > are currently not supported for link headers.
297+ </para >
298+ </section >
265299
266300 <section >
267301 <title >Prevent Recursive Injection</title >
268302 <para >
269303 By default, Jersey will try to recursively find all <literal >@InjectionLink</literal > annotations in
270- the members of your object unless this member is annotated with <literal >@XmlTransient</literal >.
304+ the members of your object unless this member is annotated with <literal >@XmlTransient</literal >.
271305
272- But in some cases, you might want to control which member will be introspected regardless of the
306+ But in some cases, you might want to control which member will be introspected regardless of the
273307 <literal >@XmlTransient</literal > annotation.
274308
275- You can prevent Jersey to look into an object by adding <literal >@InjectLinkNoFollow</literal > to a field.
309+ You can prevent Jersey to look into an object by adding <literal >@InjectLinkNoFollow</literal > to a field.
310+
311+ <programlisting language =" java" >@InjectLinkNoFollow
312+ Context context;</programlisting >
313+ </para >
314+ </section >
315+
316+
317+ <section >
318+ <title >Meta-annotation support</title >
319+ <para >
320+ The <literal >@ProvideLink</literal > annotation can be used as a meta-annotation, i.e., annotating your own annotation.
321+ This enables you to create custom annotations to reuse <literal >@ProvideLink</literal > configurations instead of
322+ copy pasting them on each method. There is a special marker class <literal >ProvideLink.InheritFromAnnotation</literal >
323+ that can be used in place of the actual entity class, this indicates that the <literal >Class< ?> value()</literal >
324+ from the custom annotation should be used instead.
325+
326+ Repeated annotations are currently unsupported for this feature. Also the <literal >Class< ?> value()</literal >
327+ method must return a single class and not an array of classes.
328+ </para >
329+
330+ <para >
331+
332+ Here is an example (getter/setter omitted for brevity) of how a meta annotation can be used.
333+ The example app uses a <literal >Page</literal > class as a base class for all entities that contain paged data.
334+
335+ <programlisting language =" java" >public class Page {
336+ private int number;
337+
338+ private int size;
339+
340+ private boolean isPreviousPageAvailable;
341+
342+ private boolean isNextPageAvailable;
343+
344+ @InjectLinks
345+ private List< Link> links;
346+ }</programlisting >
276347
277- <programlisting language =" java" >
278- @InjectLinkNoFollow
279- Context context;
280- </programlisting >
348+ Instead of duplicating the <literal >@ProvideLink</literal > annotations for the next and previous links on every
349+ method, we create the following <literal >@PageLinks</literal > annotation.
350+
351+ <programlisting language =" java" >@ProvideLink(value = ProvideLink.InheritFromAnnotation.class, rel = "next",
352+ bindings = {
353+ @Binding(name = "page", value = "${instance.number + 1}"),
354+ @Binding(name = "size", value = "${instance.size}"),
355+ }, condition = "${instance.nextPageAvailable}")
356+ @ProvideLink(value = ProvideLink.InheritFromAnnotation.class, rel = "prev",
357+ bindings = {
358+ @Binding(name = "page", value = "${instance.number - 1}"),
359+ @Binding(name = "size", value = "${instance.size}"),
360+ }, condition = "${instance.previousPageAvailable}")
361+ @Target({ElementType.METHOD})
362+ @Retention(RetentionPolicy.RUNTIME)
363+ @Documented
364+ public @interface PageLinks {
365+ Class< ?> value();
366+ }</programlisting >
367+
368+ The annotation can the then be used on the resource methods with the actual entity class as <literal >value</literal >.
369+
370+ <programlisting language =" java" >@PageLinks(OrderPage.class)
371+ @GET
372+ public Response list(@QueryParam("page") @DefaultValue("0") int page,
373+ @QueryParam("size") @DefaultValue("20") int size)</programlisting >
374+
375+ The entity just extends from <literal >Page</literal > and declares its content. It is necessary to use distinct classes
376+ instead of just a generic page to have a unique target for <literal >@ProvideLink</literal >, otherwise every method
377+ annotated with <literal >@ProvideLink(value=Page.class)</literal > would contribute to the entity.
378+
379+ <programlisting language =" java" >public class OrderPage extends Page {
380+ private List< Order> orders;
381+ }</programlisting >
281382 </para >
282383 </section >
283384
0 commit comments