On Dec 16, 2009, at 12:30 AM, Owen Jacobson wrote:
> Thanks for the feedback, Paul. Commentary inline below:
>
> On Dec 15, 2009, at 4:05 AM, Paul Sandoz wrote:
>
>> Hi Owen,
>>
>> Implicit views, as named, are implicitly implemented by Jersey,
>> thus the only thing they can return as the model is the controller
>> itself.
>
> ...
>
>>> 2. What's the rationale behind passing the JAX-RS resource
>>> instance to the JSP as "it" rather than the value returned from
>>> the request handler method?
>>
>> The controller is the only thing that is consistently available to
>> act as the model. There is no way, currently, for the controller to
>> tell Jersey what the model should be for the set of implicit views
>> (there can be a number of implicit views associated with the
>> controller, where the name of the implicit view defines the path,
>> with a special case for "index").
>
> For every other type of view (eg. an XML view provided by JAXB, or a
> custom format from an @Provider implementation of MessageBodyWriter)
> the object used to generate the wire representation is the return
> value of the resource method used to process the request, no? So
> it's at least surprising (well, to me) that for an HTML view backed
> by a JSP Jersey passes some other object. If nothing else, I think
> this could do with more thorough documentation. I'm still not sure I
> understand why this is so.
>
> May I assume that for
>
> @Path("/hello")
> public class Hello {
> @GET
> @Produces("application/xml")
> public HelloDocument getIndex() {
> return new HelloDocument();
> }
> }
>
> when Jersey decides to use an implicit JSP view that it will *never*
> invoke getIndex() itself, but instead only make the routing decision
> and then immediately forward to the appropriate JSP? I *think*
> that's what you're imply, and if so I can sort of see it.
>
Correct. The JSP can of course do ${it.index}.
> I think this also means that implicit views interact badly with
> resources in the form
>
> @Path("/hello")
> public class Hello {
> @GET
> @Produces("application/xml")
> public Response getIndex() {
> return Response.ok(new HelloDocument()).build();
> }
> }
>
> in that the JSP controls things like the response status and
> headers, rather than the JAX-RS controller.
There is no conflict as such here because getIndex will not be called
unless the JSP does so, or "application/xml" is preferred over what is
declared implicitly.
>
>>>
>>> 3. Is it possible to configure Jersey to pass the resulting
>>> HelloDocument bean to the JSP as "it", instead of the Hello
>>> instance?
>>
>> Yes, but you have to turn the implicit view into an explicit view.
>> But as a consequence you loose the prioritization feature and will
>> need to "normalize" the accept header.
>
> Looking closer at the Accept: header Safari &c generate, I'm tempted
> to call this a UA bug rather than a surprising Jersey behaviour.
> From the bookstore app's header dumper, Accept = [application/
> xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/
> png,*/*;q=0.5] suggests Safari is actually preferring XML (or XHTML)
> over HTML, which is... creative.
Yes, in the wild wild web browsers do many strange things.
> I might investigate using client-side XSLT for the UI version
> instead of server-side (JSP) HTML rendering, as much as I shudder at
> the thought.
>
> How hard is writing a MessageBodyWriter that delegates to JSP?
Very easy. See the Jersey source code here:
http://fisheye4.atlassian.com/browse/jersey/trunk/jersey/jersey-server/src/main/java/com/sun/jersey/server/impl/container/servlet/JSPTemplateProcessor.java?r=HEAD
Note that it is important when RequestDispatcher.forward is invoked
that non-proxied instances of HttpServletRequest and
HttpServletResponse be utilized, otherwise the servlet container barfs.
> It seems like that might be a better map for what I want to do (and
> more portable between JAX-RS implementations, to boot): I only want
> the JSP engine to convert the response entity object (either the
> resource itself, the return value from a resource method, or the
> entity associated with a Response object returned by a resource
> method) into a representation. I don't want JSP to handle the bulk
> of the request.
>
If you do not want to maintain your own MessageBodyWriter using
explicit views, resource methods returning Viewable, should work well
for you.
>> For implicit views to work in conjunction with resource methods
>> views you need to do something like the following:
>>
>> @Path("/hello")
>> @ImplicitProduces("text/html;qs=5")
>> public class Hello {
>> @GET
>> @Produces("application/xml")
>> public HelloDocument getXml() {
>> return new HelloDocument();
>> }
>> }
>>
>> The view can then access the property "index" to obtain the
>> HelloDocument instance. Note the "qs" parameter on the
>> @ImplicitProduces value. The "qs" value is multiplied by the "q"
>> value in the accept header thus the server is biasing to return
>> text/html over application/xml.
>>
>> See the bookstore sample for such cases:
>>
>> http://download.java.net/maven/2/com/sun/jersey/samples/bookstore/1.1.4.1/bookstore-1.1.4.1-project.zip
>
> Ah, thanks.
>
> I'd been looking at a pre-1.0 version of the bookstore, which left
> me with a few other head-scratchers. It seems the link where I
> downloaded it from now points to the 1.0.3 samples bundle; I hadn't
> found an obvious 1.1 samples download link in the docs.
>
OK. If you go to jersey.dev.java.net and click on the big download
button you will be able to read the dependencies section of the user
guide that will give you some information on the samples.
Paul.