users@jersey.java.net

Ideas on MVC support

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 12 Feb 2008 13:06:11 +0100

Hi,

Below are some ideas on MVC support for Jersey. Sorry about the length.
I wanted to 'save' my ideas as well as giving people an opportunity to
comment and contribute if they so wish before i start diving in and
developing.

Paul.

Implicit use of templates with resource class as model
------------------------------------------------------

Given a class:

   foo.Resource

And a template:

   <context>/foo/Resource/abc.jsp

If the request path matches "abc" and is an HTTP GET request then the
instance of foo.Resource will be passed to the template "abc.jsp" to
produce the response.

In general there can be a URI rule on a resource class that occurs first
for matching:

   (<expression for path segment>?)(/)?

The rule is accepted if:

1) the matching path segment is empty, there is an 'index' template and
    there is no @GET method implemented on the associated resource class;

2) the matching path segment is non-empty, and the encoded characters of
    that segment match a template with the same name, and there is no
    @GET method with an @Path value that has the same name as the
    template; or

3) the matching path segment matches a static resource of the same name.


Explicit use of templates with resource class returning a model
---------------------------------------------------------------

If there is a GET method on foo resource

   @GET
   Model get() { ... }

and there is a template:

   <context>/foo/Resource/index.jsp

Then the Model instance is the input to the template index.jsp

If there is a GET method on foo resource

   @GET
   @Path("abc")
   Model getAbc() { ... }

and there is a template:

   <context>/foo/Resource/abc.jsp

Then the Model instance is the input to the template abc.jsp

If there is a GET method on foo resource

   @GET
   @Path("abc/{id}")
   Model getAbc() { ... }

and there is a template:

   <context>/foo/Resource/abc%2F{id}.jsp

Then Model is the input to the template abc%2F{id}.jsp

This is a little odd. It sort of breaks the hierarchical model. This
path will not be matched by the implicit URI rule.

The existence of such templates can be verified at initiation time and
can be input into the implicit approach to determine acceptance.

If a GET method has a template associated with it then it returns a
model that is passed to the template for processing.


Template inheritance
--------------------

If there are classes:

    @Path("foo")
    class foo.Resource

    @Path("bar")
    class bar.Resource extends foo.Resource { ... }

And templates:

     <context>/foo/Resource/abc.jsp

     <context>/foo/Resource/xyz.jsp

Then class bar.Resource will inherit templates from foo.Resource unless
it overrides them. So a path "bar/abc" will match the template abc.jsp
and use the model that is an instance of bar.Resource.


Choice of template name
-----------------------

    @Path("foo")
    @Template("welcome")
    class foo.Resource {

       @GET String get() { ... }

       @GET @Path("abc") @Template("xyz") String getAbc() { ... }

    }

A path matching "foo" would pass the String instance returned from the
"get" method to the template "<context>/foo/welcome".

A path matching "foo/abc" would pass the String instance returned from
the "getAbc" method to the template "<context>/foo/xyz".


Templates for other HTTP methods
--------------------------------

    @Path("foo")
    class foo.Resource {

       @POST @Template("post") String post() { ... }

    }

A path matching "foo" with the HTTP method POST would pass the String
instance returned from the "post" method to the template
"<context>/foo/post".

It seems appropriate to support implicit use of templates for only GET
methods i.e. since JAX-RS separates out HTTP methods the same should be
encouraged for templates.


Programmatic use
----------------

    @Path("foo")
    class foo.Resource {

       @HttpContext TemplateContext context;

       @GET Response get() {
         String m = ...
         return context.forwardTo("welcome", m);
       }

    }

A path matching "foo" with the HTTP method GET would obtain a String
instance "m" as the model and obtain a response from the TemplateContext
instance that represents a response to forward "m" to the template
"<context>/foo/welcome".

Alternatively we can use a specific Java type:

    @Path("foo")
    class foo.Resource {

       @GET Viewable get() {
         String m = ...
         return new Viewable("welcome", m);
       }

    }

or:

    @Path("foo")
    class foo.Resource {

       @GET Viewable get() {
         String m = ...
         return new Viewable(m);
       }

    }

In the latter case the template is implicitly determined. A Response
builder can be used with Viewable as well. I think i prefer the Viewable
instance approach. There will be a message body writer for the Viewable
type. This writer will defer to template implementations themselves that
are an extension of message body writer.


Issues/TODO
-----------

If using the non-programmatic approach should template support always be
explicit using the @Template annotation (it does not have to have a
value by default) ? Then the behavior of the resource classes will be
consistent rather than behaving differently if templates are present or
not. I think i prefer that the programmatic approach always be used for
HTTP resource methods and the non-annotated implicit approach takes
lesser precedence that the former and works for paths that don't match
the paths on HTTP resource methods and only works for HTTP GET.

Registration of template implementations. Use @Provider.

Support for localization, for example templates for French, Spanish and
English, or a properties mechanism for one template with translated
property files.

Support for content types, for example templates returning XML, HTML
etc. based on client accept header.


-- 
| ? + ? = To question
----------------\
    Paul Sandoz
         x38109
+33-4-76188109