users@jersey.java.net

Re: Generating urls and controlling rendering/serialization

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 04 Mar 2008 14:46:36 +0100

On Mar 4, 2008, at 1:15 AM, Jo Størset wrote:

> Hi,
>
> what I tried to do was use the implicit viewable mechanism, that's
> why I get
>
> java.lang.IllegalArgumentException: A message body writer for Java
> type, class no.uio.total.frida.resources.Test, and MIME media type,
> text/html, was not found
>
> I tried using an explicit Viewble as well, and that worked. Thanks
> for the help, I didn't find the related classes by myself (the
> bookstore only uses implicit views).
>
> Den 3. mars. 2008 kl. 14.57 skrev Paul Sandoz:
>
>> If you can send me your Freemarker code i may be able to get
>> something working for you.
>
> My web.xml looks like this:
>
> <servlet>
> <servlet-name>Resources</servlet-name>
> <servlet-class>no.uio.total.spring.SpringServlet</servlet-class>
> <init-param>
> <param-
> name>com.sun.ws.rest.config.property.resourceConfigClass</param-name>
> <param-value>com.sun.ws.rest.api.core.PackagesResourceConfig</
> param-value>
> </init-param>
> <init-param>
> <param-name>com.sun.ws.rest.config.feature.ImplicitViewables</
> param-name>
> <param-value>true</param-value>
> </init-param>
> <init-param>
> <param-name>com.sun.ws.rest.config.feature.Redirect</param-name>
> <param-value>true</param-value>
> </init-param>
> <init-param>
> <param-name>com.sun.ws.rest.config.property.packages</param-
> name>
> <param-value>no.uio.total</param-value>
> </init-param>
> <load-on-startup>1</load-on-startup>
> </servlet>
>
> As you see I use the package config (that was how I mvn jetty:run
> to work, which out of the box seemed to have problems with the
> default setup). Based on the bookstore example I was expecting my
> templateprocessors resolve method to be called when returning a
> Test object, I haven't gotten that to work yet. In summary, the
> explicit view returned works but not the implicit feature:
>
> @Path("/test/")
> public class TestResource {
>
> @GET
> @ProduceMime("text/html")
> // Never calls my resolve method
> public Test getTest() {
> return new Test();
> }
>

We have different expectations on how implicit views work :-)

Say for example the package of the class "TestResource" is "foo",
then if there is a resource that can be loaded from the location "/
foo/TestResource/index.<tp_suffix>" then the template processor
associated with "<tp_suffix>" will get called with the model being
the instance of TestResource.

The reason why i did this is because i did not want the semantics of
HTTP methods to change if there was a template present or not. Namely
HTTP methods override any implicit behaviour and such methods need to
be explicit about the template they want to use. This is why you get
the exception that Jersey does not know what to do with the instance
of Test, it deliberately does not look for a template processor to
process a model that is an instance of Test it looks for a message
body writer that understands what to do with the type Test.

One idea i have been thinking about to avoid the use of Viewable,
while still being explicit, is to have the following:

     @GET
     @ProduceMime("text/html")
     @View("index")
     public Test getTest() {
         return new Test();
     }

which would be equivalent to:

     @GET
     @ProduceMime("text/html")
     public Viewable getTest() {
         return new Viewable("index", new Test());
     }

> @GET
> @ProduceMime("text/html")
> @Path("viewable")
> // Picks up corresponding index.ftl as expected
> public Viewable getViewable() {
> return new Viewable("index", new Test());
> }
> }
>
> I attached the processor, in case it tells you anything.
>
> <FreemarkerTemplateProcessor.java>
>

Nice, very compact. All looks OK. You might be able to put the
initialization code in the constructor and avoid the synchronized
init method and the null check in the resolve method.

Paul.