users@jersey.java.net

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

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 14 Dec 2009 20:45:38 +0100

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