users@jersey.java.net

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

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 15 Dec 2009 10:31:31 +0100

On Dec 14, 2009, at 10:28 PM, Yoryos wrote:

> Hi Paul,
>
> I will try to create a proof of concept tag.
>

Thanks, i may try and do some investigations as well today since i am
proposing this. But, i have to fully admit i do not have much
experience writing custom tags!


> 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!
>

Interesting. Do you know what advantages that brings to Grails?

 From your initial proposal i understand that model naming is required
so that models from different views do not conflict. If we can avoid
such a conflict by other means then what advantages would such naming
give us?

Paul.

> 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
>>>
>>>
>>
>>
>
>