users@jersey.java.net

Re: [Jersey] Trying to include a resource class from jsp

From: Yoryos <valotas_at_gmail.com>
Date: Mon, 14 Dec 2009 23:28:02 +0200

Hi Paul,

I will try to create a proof of concept tag.

Of course I still think that to be able to name the model is a good idea.
Maybe I'm affected by the way grails works with the model!

On Mon, Dec 14, 2009 at 21:45, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:

> Hi Yoryos,
>
> I would like to explore a custom tag to see if that solves the problem more
> elegantly than making modifications to Viewable that add additional, non
> required, options.
>
> Usually you have one model per-view hence why there is a fixed name. I do
> not see why that assumption has to change when supporting view inclusion.
>
> Sorry for pushing back a bit, i know you have spent some time investigating
> this, but i want to ensure we properly explore the area before we commit to
> a solution.
>
>
> The main advantages to exploring a custom tag solution as i see it is
> that the contract of viewable between the controller and the view does not
> change. It will work without modification to the controller code, and views
> do not require modification to refer to a different model name. No
> modification to code or existing views are required if it is decided to
> include a view from within another view, which is included from another view
> and so on. Included views will also be isolated from the parent thus
> ensuring modularity of views.
>
> I suggested looking at the existing Include as an example of how one can
> support stack-based inclusion (notice how the "resovingClass" attribute is
> essentially pushed and popped) and was not suggesting that inclusion by
> "path" use a similar mechanism to find the class. I was thinking a long the
> lines of:
>
> <rbt:include path="x/y/z"/>
>
> where a RequestDispatcher would be obtained as follows:
>
> RequestDispatcher disp = sc.getRequestDispatcher("x/y/z");
>
> Also, i was wondering if it was possible to override the existing JSP
> include
>
> I am guessing such a solution is possible, but of course this is
> theoretical until code is run, and that solution will require no
> modification to the existing Jersey API.
>
> Paul.
>
>
> On Dec 12, 2009, at 9:36 PM, Yoryos wrote:
>
> I've been thinking on this a little bit. First of all I personally believe
> that the developer of a web application should have the freedom to choose
> the name of the variables he/she binds to the request scope to be used by
> the view technology. Whatever that is. As the naming takes place
> in com.sun.jersey.server.impl.container.servlet.RequestDispatcherWrapper
> class using a ResolvedViewable class that was previously putted at
> the HttpContext properties, the only way to name the model to something
> different than 'it', it would be to have it from ResolvedViewable. As
> ResolvedViewable extends Viewable the only thing needed is another property
> at that class. Of course someone could just implement this with a slightly
> modified MessageBodyWriter witch jersey will happily supports without any
> further modifications. So let's say that this is an idea to improve a little
> bit the ViewableMessageBodyWriter and generally the templating support of
> jersey. I don't know if I should create another issue for that with an
> implementation of this custom ViewableMessageBodyWriter. I would have done
> it already if this class wasn't final but after Pauls email it is easier to
> do it!
>
> Now as for the idea of providing a custom jsp tag for including the
> jsp/html output response of a resource class. I had a look at the current
> implementation of jsp tag
> (com.sun.jersey.server.impl.container.servlet.Include) as Paul suggests. The
> "easy" part there, is that someone should just look for some jsps and
> include the first one it finds.
>
> Now in our case there is a tricky part witch is that the user is asking for
> a resource class by it's uri. That means that we should force jersey to do
> whatever it does to find the class that maps to this uri. As far as I can
> understand we have to do something like the
> com.sun.jersey.spi.container.servlet.ServletContainer does, witch is a
> service method call of the initialized webComponent object. I haven't had a
> deeper look to see where jersey actually looks for the class that maps to a
> specific uri, but even if WebContainer isn't the place that this takes
> place, we still have to reimplement this mechanism inside the tag, unless we
> are able to get the object that actually does this thing (the mapping).
>
> Considering that we have the actual class we are interesting and more
> specific the Viewable result of it, we can replace the 'it' at the request
> scope with the new one at the doStartTag of the custom tag and rebind the
> old one at doEndTag method. An even better approach would be to bind the new
> model to the page scope (I'm not completely sure if this is possible as it's
> been a while since I last had to deal with custom tags), so you got the
> stack-based solution without doing anything as the container will first look
> at the page scope for 'it' and then move to the request scope. This will
> work of course if you will not have any other king of includes inside your
> included jsp (again I'm not completely sure if this is the case as I haven't
> test it yet).
>
> Now I don't really have a deep knowledge of Jersey but I think a small
> modification to the ServletContainer and Viewable classes gives a good
> solution to the problem and it will be backwards compatible as I can't think
> of a scenario where such a modified mechanism would cause problems. This is
> because right now included requests don't get served by jersey and even if
> they do get served, jersey does not use the included uri to serve the
> response but the original one. This sounds to me like a bug itself! And in
> case of the modification to Viewable if someone does not provide a name it
> will get a default one (witch will be the 'it').
>
> That is my thoughts on the problem. Do you thing that a custom tag solution
> is the way to go?
>
> Regards,
> Yoryos
>
>
> On Fri, Dec 11, 2009 at 17:10, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:
>
>> Hi Yoryos,
>>
>> I still need to look in greater detail, but what occurs to me is one might
>> require a stack-based solution where for each include where "it" is pushed
>> on the stack and then popped off, since a view could include another view
>> and so on.
>>
>> It would be good if we can find a solution without having to modify
>> Viewable or having to define additional semantics on resource classes as i
>> think such solutions break the layering.
>>
>> To support this it might require that we introduce a new tag. Much like
>> Jersey has its own include tag for including other JSPs using the resource
>> class to find a suitable JSP we might be able to do something similar for
>> the inclusion of views of other resources.
>>
>> So i recommend taking a closer look at:
>>
>> com.sun.jersey.server.impl.container.servlet.Include
>>
>> Paul.
>>
>> On Dec 11, 2009, at 9:06 AM, Yoryos wrote:
>>
>> Ok, thank you! I'll try to work on that this weekend! As a first solution
>> on my mind would be to have Viewable to be able to have another String
>> property with a default value 'it', that can be defined at the
>> initialization of the class. Then we can use it's value instead of a 'it' to
>> bind the model to the request scope at the RequestDispatcheWrapper (I don't
>> remember the exact name). I'll have a closer look though!
>>
>> Yoryos
>>
>>
>> On Wed, Dec 9, 2009 at 12:33, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:
>>
>>> Hi Yoryos,
>>>
>>> I am very sorry i have not had enough time to look in detail. I require a
>>> 2 to 4 hour slot of free time to really think about this :-(
>>>
>>> Here off the top of my head is how the Viewable is processed:
>>>
>>> 1) A Viewable is returned from a resource method;
>>>
>>> 2) The Viewable in 1) is processed
>>> by com.sun.jersey.server.impl.template.ViewableMessageBodyWriter
>>>
>>> 3) The ViewableMessageBodyWriter code is as follows:
>>>
>>> @Context HttpContext hc;
>>>
>>> @Context UriInfo ui;
>>>
>>> @Context TemplateContext tc;
>>>
>>> public boolean isWriteable(Class<?> type, Type genericType,
>>> Annotation[] annotations, MediaType mediaType) {
>>> return Viewable.class.isAssignableFrom(type);
>>> }
>>> public void writeTo(Viewable v,
>>> Class<?> type, Type genericType, Annotation[] annotations,
>>> MediaType mediaType, MultivaluedMap<String, Object>
>>> httpHeaders,
>>> OutputStream entityStream) throws IOException {
>>> final ResolvedViewable rv = resolve(v);
>>> if (rv == null)
>>> throw new IOException("The template name, " +
>>> v.getTemplateName() +
>>> ", could not be resolved to a fully qualified
>>> template name");
>>>
>>>
>>> hc.getProperties().put("com.sun.jersey.spi.template.ResolvedViewable", rv);
>>> rv.writeTo(entityStream);
>>> }
>>>
>>> private ResolvedViewable resolve(Viewable v) {
>>> if (v instanceof ResolvedViewable) {
>>> return (ResolvedViewable)v;
>>> } else {
>>> return tc.resolveViewable(v, ui);
>>> }
>>> }
>>>
>>> 4) The TemplateContext is used to to transform the Viewable into a
>>> ResolvedViewable, see:
>>>
>>>
>>> https://jersey.dev.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/spi/template/TemplateContext.html
>>> #resolveViewable%28com.sun.jersey.api.view.Viewable,%20javax.ws.rs.core.UriInfo%29
>>>
>>> The above method is implemented by TemplateFactory:
>>>
>>> public ResolvedViewable resolveViewable(Viewable v, UriInfo ui) {
>>> if (v.isTemplateNameAbsolute()) {
>>> return resolveAbsoluteViewable(v);
>>> } else if (v.getResolvingClass() != null) {
>>> return resolveRelativeViewable(v, v.getResolvingClass());
>>> } else {
>>> final List<Object> mrs = ui.getMatchedResources();
>>> if (mrs == null || mrs.size() == 0)
>>> throw new TemplateContextException("There is no last
>>> matching resource available");
>>>
>>> return resolveRelativeViewable(v, mrs.get(0).getClass());
>>> }
>>> }
>>>
>>>
>>> 5) Then the resolved viewable writes itself out to the output stream:
>>>
>>> public void writeTo(OutputStream out) throws IOException {
>>> template.writeTo(getTemplateName(), getModel(), out);
>>> }
>>>
>>> which defers to the TemplateProcessor that resolved the Viewable.
>>>
>>> I recommend doing a debug session tracing through the steps.
>>>
>>> Paul.
>>>
>>> On Dec 6, 2009, at 9:34 AM, Yoryos wrote:
>>>
>>> Hello all,
>>> I'm trying to make jersey be able to handle included requests. That means
>>> that having a jsp to be able to include a uri that maps to a resource class.
>>> Of course the resource class should be able to produce html.
>>>
>>> I'm using the jersey filter. So the first thing I've done was to let the
>>> Servlet container use the jersey filter not only for the actual requests but
>>> also for the forwarding and included ones. This can be done by adding the
>>> following to the mapping of the filter at web.xml:
>>> <dispatcher>REQUEST</dispatcher>
>>> <dispatcher>FORWARD</dispatcher>
>>> <dispatcher>INCLUDE</dispatcher>
>>>
>>> This didn't work out of the box. So I had to take a look at the source in
>>> order to have a better view of what is going on. Looking at the source of
>>> jersey, I found that ServletContainer class does not handle included
>>> requests at all. So I had also to fix that too. I've posted the code on a
>>> previous email and also created an issue (
>>> https://jersey.dev.java.net/issues/show_bug.cgi?id=432) with a maven
>>> project with a working solution.
>>>
>>> A working solution means that you can include a resource class with in
>>> jsp and get html that you would have calling only the uri that maps to the
>>> included class.
>>>
>>> With a modified filter you will be able to just include resource classes
>>> without any model as jersey binds the model always to 'it' at the request
>>> scope. To overcome this I had to also modify a little bit the default
>>> default jsptemplate and instead of binding the model to 'it', bind it to
>>> something like '[ResourceClass.getClass().getSimpleName()]Model'
>>>
>>> The above solution does not require to change Jersey's sources and works
>>> ok but it is not the best one. I mean the user should be able to define the
>>> name of the model at the request scope if he wants to and it would be nice
>>> to be able to have an annotation for methods that should return only results
>>> of type Viewable and it will be called only when the resource is about to be
>>> included.
>>>
>>> This is where I would like some help. Can someone explain the exact
>>> procedure of serving a Resource class with a Viewable because I'm pretty
>>> lost when tried to read the source. At least from where should I start
>>> reading.
>>>
>>> I hope I described ok the whole situation!
>>>
>>> Yoryos
>>>
>>>
>>>
>>
>>
>
>