users@jersey.java.net

Re: Ideas on MVC support

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 13 Feb 2008 17:07:13 +0100

Hi,

It was politely pointed out to me that what i wrote was a bit too much
of a brain dump. So what follows below is a second try with a specific
proposal that is hopefully clearer and more precise.

Paul.

Template structure layout
-------------------------

    <context>/
       foo/
          Foo/
             super.jsp # an inheritable template
             override.jsp
       bar/
          BarResource/
             index.jsp
             item.jsp
             create.jsp
       baz/
          BazResource/
             static.html # a static file
             override.jsp # overrides that in foo/Foo/

Classes
-------

    package foo;
    public class Foo { ... }

    package bar;
    @Path("bar") public class BarResource extends foo.Foo {

       @Path("{id}") @GET public Viewable item(
             @PathParam("id") String id) {
          String model = ...;
          return new Viewable("item", model);
       }

       @POST public Response create() {
          URI cu = ...
          Viewable v = new Viewable("create", this);
          return Response.created(u).entity(v).build();
       }

    }

    package baz;
    @Path("baz") public class BazResource extends foo.Foo {
       @GET public String get() {
          return "content";
       }
    }


Request Template Model
------------------------------------------------------------------------
GET /bar /bar/BarResource/index.jsp instance of BarResource

GET /bar/1 /bar/BarResource/item.jsp instance of String created
                                               by BarResource.item
GET /bar/super " "
GET /bar/index " "
GET /bar/item " "
GET /bar/create " "

POST /bar /bar/BarResource/create.jsp instance of BarResource
                                               returned by
                                               BarResource.create

GET /baz N/A N/A specific content is
                                               returned

GET /baz/ N/A N/A the static file is
     static.html returned

GET /baz/super /foo/Foo/super.jsp instance of BazResource

GET /baz/ /bar/Baz/override.jsp instance of BazResource
     override


Rules
-----

- The directory path of templates and static files for a resource class
   is specified by the fully qualified name of that class converted to a
   path.

- A template, "xxxx.yyyy", consists of a template name "xxxx" and
   template meta-data "yyyy", where "yyyy" describes the template
   technology and potentially the media type and language.

- A resource class will inherit the templates and static files from the
   direct and indirect super classes. A class can override the templates
   or static files of a direct or indirect super class.

- If a request URI path matches a HTTP method on a resource then that
   method is processed. An HTTP method takes precedence over matching of
   template and static files associated with a resource.

   - A HTTP method may return a Viewable object that contains the
     template name to use and the instance of the model passed to the
     template.

- If a request URI path does not match any HTTP methods but matches the
   template name of a template associated with the resource class then
   that template is selected and the model is the instance of the
   resource class.

- If a request URI path does not match any HTTP methods or templates
   but matches a static file associated with the resource class then that
   static file is returned.

- If a request URI path does not match a HTTP method, template or static
   file a 404 is returned.


Questions/thoughts
------------------

- Should static files take precedence over HTTP methods?

- Should one use an annotation on the HTTP method to specify the
   template name?

       @Viewable("item")
       @Path("{id}") @GET public String show(
             @PathParam("id") String id) {
          String model = ...;
          return model;
       }



Paul Sandoz wrote:
> 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