Chapter 18. MVC Templates
Prev |  | Next

Links: Table of Contents | Single HTML

## Chapter 18. MVC Templates

Jersey provides an extension to support the Model-View-Controller (MVC) design pattern. In the context of Jersey components, the Controller from the MVC pattern corresponds to a resource class or method, the View to a template bound to the resource class or method, and the Model to a Java object (or a Java bean) returned from a resource method.

## 18.1. Dependencies

Jersey MVC templating support is provided by Jersey as a set of (three) extension modules:

- jersey-mvc

  The base module that provides API and extension SPI for MVC templating support in Jersey. This module is required by any particular MVC templating engine integration module that implements the exposed SPI.

- jersey-mvc-freemarker

  An integration module with Freemarker-based templating engine. The module provides a custom `TemplateProcessor` for Freemarker templates and a set of related engine-specific configuration properties.

- jersey-mvc-jsp

  An integration module for JSP-based templating engine. The module provides a custom `TemplateProcessor` for JSP templates, custom tag implementation and a set of related engine-specific configuration properties.

### Note

In a typical set-up projects using the Jersey MVC templating support would depend on the base module that provides the API and SPI and a single templating engine module for the templating engine of your choice. These modules need to be mentioned explicitly in your `pom.xml` file.

If you want to use just templating API infrastructure provided by Jersey for the MVC templating support in order to implement your custom support for a templating engine other than the ones provided by Jersey (JSP/Freemarker), you will need to add the base jersey-mvc module into the list of your dependencies:

    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-mvc</artifactId>
        <version>2.3.1</version>
    </dependency>

To use one of the templating engines for which Jersey provides the integration implementation (JSP/Freemarker) in your project, you need to add the jersey-mvc-jsp or jersey-mvc-freemarker module to your `pom.xml` respectively:

    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-mvc-jsp</artifactId>
        <version>2.3.1</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-mvc-freemarker</artifactId>
        <version>2.3.1</version>
    </dependency>

Both of these modules transitively depend on the base `jersey-mvc`, so it is not necessary to add the base `jersey-mvc` module explicitly into your dependency list, however it is a recommended Maven practice to do so.

If you are not using Maven you need to make sure to have all required transitive dependencies (see jersey-mvc/jersey-mvc-freemarker/jersey-mvc-jsp) on the classpath.

## 18.2. Registration and Configuration

To use capabilities of Jersey MVC templating support in your JAX-RS/Jersey application you need to register Features provided by the modules mentioned above. For `jersey-mvc` it is MvcFeature, for `jersey-mvc-jsp` it's JspMvcFeature and for `jersey-mvc-freemarker` it is FreemarkerMvcFeature.

### Note

Both `JspMvcFeature` and `FreemarkerMvcFeature` also register `MvcFeature` so you don't need to register it explicitly when using these JSP/Freemarker modules.

Example 18.1. Registering `MvcFeature`

    new ResourceConfig()
        .register(org.glassfish.jersey.server.mvc.MvcFeature.class)
        // Further configuration of ResourceConfig.
        .register( ... );

Example 18.2. Registering `JspMvcFeature`

    new ResourceConfig()
        .register(org.glassfish.jersey.server.mvc.jsp.JspMvcFeature.class)
        // Further configuration of ResourceConfig.
        .register( ... );

### Important

Jersey web applications that want to use MVC templating support feature should be registered as Servlet filters rather than Servlets in the application's `web.xml`. The `web.xml`-less deployment style introduced in Servlet 3.0 is not supported at the moment for web applications that require use of Jersey MVC templating support.

Each of the three MVC modules contains a `*Properties` (e.g. `FreemarkerMvcProperties`) file which defines a set of properties that could be set in a JAX-RS `Application` / `ResourceConfig` in order to take effect, see the Example 18.3, “Setting `MvcProperties.TEMPLATE_BASE_PATH` value in `ResourceConfig`” and Example 18.4, “Setting `FreemarkerMvcProperties.TEMPLATE_BASE_PATH` value in `web.xml`”.

Following list contains description of the available properties:

- `MvcProperties.TEMPLATE_BASE_PATH` - "`jersey.config.server.mvc.templateBasepath`"

  The base path where templates are located.

- `FreemarkerMvcProperties.TEMPLATE_BASE_PATH` - "`jersey.config.server.mvc.templateBasepath.freemarker`"

  The base path where Freemarker templates are located.

- `JspMvcProperties.TEMPLATE_BASE_PATH` - "`jersey.config.server.mvc.templateBasepath.jsp`"

  The base path where JSP templates are located.

Example 18.3. Setting `MvcProperties.TEMPLATE_BASE_PATH` value in `ResourceConfig`

    new ResourceConfig()
        .property(MvcProperties.TEMPLATE_BASE_PATH, "templates")
        .register(MvcFeature.class)
        // Further configuration of ResourceConfig.
        .register( ... );

Example 18.4. Setting `FreemarkerMvcProperties.TEMPLATE_BASE_PATH` value in `web.xml`

    <servlet>
        <servlet-name>org.glassfish.jersey.examples.freemarker.MyApplication</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>org.glassfish.jersey.examples.freemarker.MyApplication</param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.server.mvc.templateBasePath.freemarker</param-name>
            <param-value>freemarker</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

## 18.3. Explicit vs. Implicit View Templates

### Note

Some of the passages/examples from this and the next section was taken from MVCJ blog article written by Paul Sandoz earlier.

In Jersey 2.0, the base MVC API (excluding the SPI part) consists of two classes (in the `org.glassfish.jersey.server.mvc` package in base MVC module) that we will explore in more detail now, namely Viewable and @Template. These classes determines which approach (explicit/implicit) you would be taking when working with Jersey MVC templating support.

### 18.3.1. `Viewable` - Explicit View Templates

In this approach a resource method explicitly returns a reference to a view template and the data model to be used. For this purpose the Viewable class has been introduced in Jersey 1 and is also present (under a different package) in Jersey 2. A simple example of usage can be seen in Example 18.5, “Using `Viewable` in a resource class”.

Example 18.5. Using `Viewable` in a resource class

    package com.foo;

    @Path("foo")
    public class Foo {

        @GET
        public Viewable get() {
            return new Viewable("index", "FOO");
        }
    }

In this example, the `Foo` JAX-RS resource class is the controller and the `Viewable` instance encapsulates the provided data model (`"FOO"` string) and a named reference to the associated view template (`"index"`).

The template name reference `"index"` is a relative value that Jersey will resolve to its absolute template reference using the fully qualified class name of `Foo` (more on resolving relative template name to the absolute one can be found in the JavaDoc of Viewable class), which, in our case, is:

    "/com/foo/Foo/index"

Jersey will then search all the registered template processors (see Section 18.5, “Custom Templating Engines”) to find a template processor that can resolve the absolute template reference further to a "processable" template reference. If a template processor is found then the "processable" template is processed using the supplied data model.

Let's change the resource `GET` method in our `Foo` resource a little:

Example 18.6. Using absolute path to template in `Viewable`

    @GET
    public Viewable get() {
        return new Viewable("/index", "FOO");
    }

In this case, since the template reference begins with `"/"`, Jersey will consider the reference to be absolute already and will not attempt to absolutize it again. The reference will be used "as is" when resolving it to a "processable" template reference as described earlier.

### Tip

All HTTP methods may return `Viewable` instances. Thus a `POST` method may return a template reference to a template that produces a view that is the result of processing an HTML Form.

### 18.3.2. `@Template` - Implicit View Templates

#### 18.3.2.1. Resource classes

A resource class can have templates implicitly associated with it via @Template annotation. For example, take a look at the resource class listing in Example 18.7, “Using `@Template` on a resource class”.

Example 18.7. Using `@Template` on a resource class

    @Path("foo")
    @Template
    public class Foo {

        public String getFoo() {
            return "FOO";
        }
    }

The example above uses a lot of conventions and requires some more explanation. First of all, you may have noticed that there is no resource method defined in this JAX-RS resource. Also, there is no template reference defined. In this case, since the `@Template` annotation placed on the resource class does not contain any information, the default relative template reference `"index"` will be used. Later it will get resolved to an absolute `"/com/foo/Foo/index"` template reference. As for the missing resource methods, a default `@GET` method will be implicitly generated by Jersey for the `Foo` resource (our MVC Controller). The implementation of the implicitly added resource method performs the equivalent of the following explicit resource method:

    @GET
    public Viewable get() {
        return new Viewable("index", this);
    }

As you can see, the resource class serves in this case also as a model. Producible media types are determined based on the `@Produces` annotation declared on the resource class, if any.

### Note

In case of a resource class-based implicit MVC view template, the controller is also the model. In this case the template reference `"index"` is special, it is the template reference associated with the controller itself.

Implicit sub-resource templates are also supported, for example, for a template reference `"bar"` that resolves to an absolute template reference `"/com/foo/Foo/bar"` that in turn resolves to a processable template reference. Following `@GET` method is also implicitly added to the `Foo` controller that performs the equivalent of the following explicit sub-resource method:

    @GET
                            @Path("{implicit-view-path-parameter}")
                            public Viewable get(@PathParameter("{implicit-view-path-parameter}") String template) {
                            return new Viewable(template, this);
                            }

In other words, a HTTP `GET` request to a `"/foo/bar"` would be handled by this auto-generated method in the `Foo` resource and would delegate the request to a registered template processor supports processing of the absolute template reference `"/com/foo/Foo/bar"`, while the model is still an instance of the JAX-RS resource class `Foo`.

#### 18.3.2.2. Resource methods

In case a resource method is annotated with @Template annotation then the return value of the method defines the MVC model part. The processing of such a method is then essentially the same as if the return type of the method was an instance of the Viewable class. If a method is annotated with `@Template` and is also returning a `Viewable` instance then the values (`resolvingClass`) from the `Viewable` instance take precedence over those defined in the annotation. Producible media types are determined from the method's `@Produces` annotation.

### Note

Implicit view templates support works dynamically (as is the case for explicit MVC) so it is possible (if the deployment system is configured correctly) to add or modify templates while the application is running.

## 18.4. JSP

As stated earlier, Jersey provides support for JSP templates in jersey-mvc-jsp extension module. There is a JSP template processor that resolves absolute template references to processable template references represented as JSP pages as follows:

Procedure 18.1. Resolving JSP processable template reference

1. if the absolute template reference does not end in `".jsp"` append this suffix to the reference; and

2. if `Servlet.getResource` returns a non-`null` value for the appended reference then return the appended reference as the processable template reference otherwise return `null` (to indicate the absolute reference has not been resolved by the JSP template processor).

Thus the absolute template reference `"/com/foo/Foo/index"` would be resolved to `"/com/foo/Foo/index.jsp"`, provided there exists a `"/com/foo/Foo/index.jsp"` JSP page in the web application.

Jersey will assign the model instance to the attribute named "`it`". So in the case of the implicit example it is possible to referece the `foo` property on the `Foo` resource from the JSP template as follows:

    <h1>${it.foo}</h1>

## 18.5. Custom Templating Engines

To add support for other (custom) templating engines into Jersey MVC Templating facility, you need to implement the TemplateProcessor and register this class into your application.

### Tip

When writing template processors it is recommend that you use an appropriate unique suffix for the processable template references. In such case it is then possible to easily support mixing of multiple templating engines in a single application without any conflicts.

Example 18.8. Custom TemplateProcessor

    @Provider
    class MyTemplateProcessor implements TemplateProcessor<String> {

        @Override
        public String resolve(String path, final MediaType mediaType) {
            final String extension = ".testp";

            if (!path.endsWith(extension)) {
                path = path + extension;
            }

            final URL u = this.getClass().getResource(path);
            return u == null ? null : path;
        }

        @Override
        public void writeTo(String templateReference,
                            Viewable viewable,
                            MediaType mediaType,
                            OutputStream out) throws IOException {
            final PrintStream ps = new PrintStream(out);
            ps.print("path=");
            ps.print(templateReference);
            ps.println();
            ps.print("model=");
            ps.print(viewable.getModel().toString());
            ps.println();
        }

    }

Example 18.9. Registering custom TemplateProcessor

    new ResourceConfig()
        .register(MyTemplateProcessor.class)
        // Further configuration of ResourceConfig.
        .register( ... );

## 18.6. Other Examples

To see an example of MVC (JSP) templating support in Jersey refer to the MVC (Bookstore) example.

Prev |  | Next
Chapter 17. Entity Data Filtering | Home | Chapter 19. Monitoring and diagnostics