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