users@jax-rs-spec.java.net

[jax-rs-spec users] Re: Feedback on Hypermedia discussion on JAX-RS expert list

From: Mattias Arthursson <mattias.arthursson_at_gmail.com>
Date: Tue, 15 Nov 2011 09:12:09 +0100

Santiago,

New comments inlined

> It might be possible to provide
> > the ability to customize link representation using e.g. a
> > MessageEnricher annotated with @Provider, which will give you access to
> > headers and entity before MessageBodyWriter is invoked. This opens up
> > for having the links in the message body if that is what you want. A
> > client counterpart for MessageEnricher might be needed.
>
> Is this not possible using JAX-RS 2.0 handlers?
>
>
You're right: provided that the WriteToHandlerContext would contain the
Link information from the response I guess this might indeed be the exact
thing we were asking for.


>
> > Should it be possible to customize the link verbosity?
>
> Link.fromResourceMethod() returns a LinkBuilder, so you should be able to
> customize the link before calling build().
>
>
Well, that would enable explicit programmatic customization, but it
wouldn't enable a server default, neither would it allow a client to
request a custom verbosity level.


> > This could be a convention, but what if your
> > representation contains multiple nested lists or objects? Maybe this
> > type of link could also have a 'path' attribute, pointing to the
> > collection/position that it relates to (e.g. in XPath, JSONPath or a
> > custom path format). This would work with the URI templates, but it
> > also opens up for serving absolute links to nested elements without
> > using a template.
>
> Sounds interesting, but I think we want to steer clear from the
> complexity of any type of "path" language in our first attempt at solving
> this problem.
>
>
You're probably right, but I still think you'll need to come up with
something else than URI templates for linking to nested items.


> > Link/LinkBuilder
> > ----------------
> > * Use of an @Rel annotation makes it impossible to handle different
> > resources in same class, e.g. machines and machine (if we need a 'self'
> > rel for both of these).
>
> Is this a major shortcoming?
>
>
If it's not absolutely necessary I don't think that the API should impose
any strict rules on what you choose to handle in a single JAX-RS resource
class. There is nothing in the current API that prevents me from doing the
above; I should be able to add Hypermedia support to an existing
application without any major restructuring.


> > This would be solved by a global @Linkable
> > annotation (with id and rel attributes), which would also make the Link
> > construction less verbose:
> > Link.from(linkableId).build(params)
>
> Ideally, I'd like to see a solution that is annotation free at this
> stage. However, that may be impractical. I'll explore @Linkable more
> --others have pointed out shortcomings of @Rel too.
>
>
Just to be perfectly clear: even though I suggest introducing a new
@Linkable annotation I still think that link specification in the response
should be programmatic. The difference between the proposed @Linkable and
the @Rel in your example is that the @Linkable value is global for the
entire application, whereas the @Rel value is local to one class, i.e. the
@Linkable value would be used in LinkBuilder in the same way that the @Rel
value in your proposed solution; for example:

Link.fromLinkable(linkableId).build(params)

> ResponseBuilder
> > ---------------
> > It would be nice to be able to append links directly in the
> > ResponseBuilder, e.g.:
> > ResponseBuilder.addLink(LinkableId, params...)
> > ResponseBuilder.addLink(ResourceClass.class, rel, params...)
> > ResponseBuilder.addLink(Link.fromResourceMethod(...).build())
> > ResponseBuilder.links(Link...)
> >
>

No comment on this? The key point with the above is that you should be able
to add links fluently using ResponseBuilder, e.g.:

ResponseBuilder.entity(machine).addLink(getClass(), "self",
machine.getId()).addLink(...).build();
or ("machine.get" is supposed to be the value of the @Linkable annotaion on
the self method in the MachineResource class):
ResponseBuilder.entity(machine).addLink("machine.get",
machine.getId()).addLink(...).build();

This is just for convenience, but I do think it would enable cleaner code
than having to build a Link array (there could still be a "links" method
that takes a Link array though).

Regards,
/Mattias