Skip to content
This repository was archived by the owner on May 28, 2018. It is now read-only.

Commit e9bc5ce

Browse files
leonard84pavelbucek
authored andcommitted
Add docs for @ProvideLink(s)
Change-Id: I7cc92ff6f6336a8539871fb04a329080f2a4208c
1 parent db33acf commit e9bc5ce

File tree

1 file changed

+121
-20
lines changed

1 file changed

+121
-20
lines changed

docs/src/main/docbook/declarative-linking.xml

Lines changed: 121 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
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
@@ -76,7 +76,7 @@
7676
<version>&version;</version>
7777
&lt;/dependency&gt;</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">&lt;dependency&gt;
@@ -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&lt;Link&gt; 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&lt;Link&gt; links</programlisting>
238-
</para>
239-
</section>
240-
241271
<section>
242272
<title>Link Headers</title>
243273
<para>
@@ -246,7 +276,7 @@ List&lt;Link&gt; 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&lt;Link&gt; 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&lt;?> 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&lt;?> 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&lt;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&lt;?> 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&lt;Order> orders;
381+
}</programlisting>
281382
</para>
282383
</section>
283384

0 commit comments

Comments
 (0)