Hi again!
On Tue, Dec 15, 2009 at 11:31, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:
>
> 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!
>
>
It's been a while since I last had to deal with jsp tags, but they are not
rocket science! I'll look at it when I'll find some free time. I'm sure it
will not be very hard!
>
> 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?
>
Well as I said I'm affected. That doesn't mean that there is so much
advantages or there isn't any workaround on this or even that this is the
way it should be. But most times I don't have only one model per page. This
is true for stuff like xml and json responses but in most cases when dealing
with html responses (witch is the case of most of the webapps) you will have
to also include other resources and use many models per request.
Of course you can create your jaxrs classes to provide you with the model
you may need (so you can do a it.somemodel) with getters (and use
inheritance and composition for complex pages witch would need complex
model) or create a map with all the stuff you need and pass this map as a
model. You can even then tweak the map instead of creating new one for other
included resources.
The only problem is that java is not so expressive and a creation of a map
just to pass a model to the view isn't very clean. I mean consider:
Map model = new HashMap()
model.put('key1', somevalue1)
model.put('key2', somevalue2)
model.put('key3', somevalue3)
return new Viewable(path, model)
to the grails/groovy equivalent:
return [key1:somevalue1, key2:somevalue2, key3:somevalue3]
At last I don't find really handy the use of 'it' inside the views. For
example when you have to deal with books in a bookstore, using BookList as
your model name would be really helpful for anyone reading the jsp to
understand that has to probably deal with a List of Books (List<Book>)
Of course I find much more cleaner and easier to use the way jersey (and
generally jaxrs implementation) deal with url mapping than grails does, and
this a reason using it!
I can understand that these issues doesn't have anything to do with JAXRS
directly, but if someone want to use it as a web framework and not just an
easy way to communicate with xml, I think that stuff like that matters. By
the way am I the only one that uses jersey as a web framework?
>
> 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?
>
>
As you can understand it is not a workaround in order for my initial
proposal to work right! It is something that I thing will help
the expressiveness of the view mechanism as is right now. That doesn't mean
that is the way to go. I would really like to hear opinions from people
using the jersey on that. It is not something that you can't do with it, but
I'm sure anyone will benefit from such an improvement.
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
>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>
>