users@jersey.java.net

Re: [Jersey] Separation of Concern between Resource and Writer

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 06 Oct 2009 14:51:35 +0200

On Oct 6, 2009, at 12:58 PM, Jan Algermissen wrote:

> Maybe I am not seeing the obvious, but I have the following issue:
>
> In my opinion it is good to have the destinction between resource
> classes that take care of request handling and interactions with the
> backend layer and message body writer classes that are responsible
> for turning domain objects into the response body.
>

I view message body writers (MBWs) as writing out representations. And
representations are headers+entity so a MBW can be responsible for
writing/modifying headers. It all depends on how you define your Java
types instances of which correspond to representations.


> I am not sure if this is the intent of JAX-RS but I think that the
> implementationof the writers should not be concerned with the
> particularities of the actual request. This should be left to the
> resource class.
>
> It seems though that it is in some cases impossible (at least with
> standard JAX-RS) to, for example, set headers (e.g. a Link header)
> in the resource class and that instead one is forced to 'clutter up'
> the writer implementation with handling the header population.
>

The only issue (based on our discussions) is when you use
StreamingOutput you cannot add headers when the write method is
called. But you can add headers when building the Response. Or use a
MBW with your own Java type that knows how to write the representation
given an instance of that type.


> What I'd like to do instead is somehow assemble/compute the
> necessary information in the resource class and pass it to the
> writer class.
>

You can assemble such information into the instance of the Java type
that is used as the entity.


> What would be the best way to do this? Is the framework extensible
> in a way that one could write annotations for this to inject the
> information onto the writer?
>

Not really. I suspect something is possible with Jersey wiring. The
tricky bit is how the resource method defines the state that should be
available when the MBW is called. IMHO i think, if one uses per-
request resource classes, instances of those can hold the state.

It is possible for the MBW to obtain the instance of the resource
class from UriInfo, so the MBW could obtain additional information
from that e.g. it could use that to resolve links if the resource
class implement a link resolving interface.

It is possible using Jersey filters to respond to annotations on the
resource method and then to decorate adapt the entity as appropriately.

Thinking of this generically it might be possible to support a MBW for
the type Linkable<T> an instance of which contains appropriate
information to resolve links related to annotations described by an
instance of T.


> Viewing this from the angle of the hypermedia constraint, the idea
> would be to determine the links to be made available to the client
> inside the resource class and pass that information to the writer
> (because the writer must put the links into the message body)
> instead of having the writer deal with determining the links itself.
>
> Makes sense?
>

Yes, that use-case helps.

It may be possible to support something like this:

   @GET
   Linkable<MyBean> get() {
     MyBean b = ...
     Links l = ...
     return new Linkable<MyBean>(b, l)
   }

or

  public class MyResource implements Linkable {
   // Linkable iface
   Links getLinks() { ... }

   @GET
   Linkable<MyBean> get() {
     MyBean b = ...
     return new Linkable<MyBean>(b)
   }
  }

where the MBW for Linkable can obtain the instance of Linkable from
UriInfo.getMatchedResources.

If using the Jersey feature of resource filters it should be possible
to support something like:

  public class MyResource implements Linkable {
   // Linkable iface
   Links getLinks() { ... }

   @Linkable
   @GET
   MyBean get() {
     MyBean b = ...
     return b;
   }
  }

Paul.