| <?xml version="1.0"?> | |
| <!-- | |
| Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. | |
| This program and the accompanying materials are made available under the | |
| terms of the Eclipse Public License v. 2.0, which is available at | |
| http://www.eclipse.org/legal/epl-2.0. | |
| This Source Code may also be made available under the following Secondary | |
| Licenses when the conditions for such availability set forth in the | |
| Eclipse Public License v. 2.0 are satisfied: GNU General Public License, | |
| version 2 with the GNU Classpath Exception, which is available at | |
| https://www.gnu.org/software/classpath/license.html. | |
| SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | |
| --> | |
| <!DOCTYPE chapter [<!ENTITY % ents SYSTEM "jersey.ent" > %ents;]> | |
| <chapter xmlns="http://docbook.org/ns/docbook" | |
| version="5.0" | |
| xml:lang="en" | |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| xmlns:xi="http://www.w3.org/2001/XInclude" | |
| xmlns:xlink="http://www.w3.org/1999/xlink" | |
| xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd | |
| http://www.w3.org/1999/xlink http://www.w3.org/1999/xlink.xsd" | |
| xml:id="mvc"> | |
| <title>MVC Templates</title> | |
| <para> | |
| 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 (Controller). | |
| </para> | |
| <note> | |
| <para> | |
| Some of the passages/examples from this chapter have been created by Paul Sandoz. | |
| </para> | |
| </note> | |
| <para> | |
| In Jersey 2, the base MVC API consists of two classes (<literal>org.glassfish.jersey.server.mvc</literal> package) | |
| that can be used to bind model to view (template), namely &jersey.server.mvc.Viewable; and &jersey.server.mvc.Template;. | |
| These classes determine which approach (explicit/implicit) you would be taking when working with Jersey MVC | |
| templating support. | |
| </para> | |
| <section> | |
| <title>Viewable</title> | |
| <para> | |
| 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 &jersey.server.mvc.Viewable; class has been introduced in Jersey 1 and is also | |
| present (under a different package) in Jersey 2 and 3. A simple example of usage can be seen in | |
| <xref linkend="mvc.example.viewable.simple"/>. | |
| <example xml:id="mvc.example.viewable.simple"> | |
| <title>Using &lit.jersey.server.mvc.Viewable; in a resource class</title> | |
| <programlisting language="java">package com.example; | |
| @Path("foo") | |
| public class Foo { | |
| @GET | |
| public Viewable get() { | |
| return new Viewable("index.foo", "FOO"); | |
| } | |
| }</programlisting> | |
| </example> | |
| </para> | |
| <para> | |
| In this example, the <literal>Foo</literal> JAX-RS resource class is the controller and the | |
| &lit.jersey.server.mvc.Viewable; instance encapsulates the provided data model (<literal>FOO</literal> string) | |
| and a named reference to the associated view template (<literal>index.foo</literal>). | |
| </para> | |
| <tip> | |
| <para> | |
| All HTTP methods may return &lit.jersey.server.mvc.Viewable; instances. Thus a &lit.http.POST; method may | |
| return a template reference to a template that produces a view as a result of processing an | |
| HTML &jaxrs.core.Form;. | |
| </para> | |
| </tip> | |
| </section> | |
| <section> | |
| <title>@Template</title> | |
| <section> | |
| <title>Annotating Resource methods</title> | |
| <para> | |
| There is no need to use &lit.jersey.server.mvc.Viewable; every time you want to bind a model to a template. To | |
| make the resource method more readable (and to avoid verbose wrapping of a template reference and model into | |
| &lit.jersey.server.mvc.Viewable;) you can simply annotate a resource method with &jersey.server.mvc.Template; | |
| annotation. An updated example, using &lit.jersey.server.mvc.Template;, from previous section is shown in | |
| <xref linkend="mvc.example.template.simple"/> example. | |
| <example xml:id="mvc.example.template.simple"> | |
| <title>Using &lit.jersey.server.mvc.Template; on a resource method</title> | |
| <programlisting language="java">package com.example; | |
| @Path("foo") | |
| public class Foo { | |
| @GET | |
| @Template(name = "index.foo") | |
| public String get() { | |
| return "FOO"; | |
| } | |
| }</programlisting> | |
| </example> | |
| </para> | |
| <para> | |
| In this example, the <literal>Foo</literal> JAX-RS resource class is still the controller as in previous | |
| section but the MVC model is now represented by the return value of annotated resource method. | |
| </para> | |
| <para> | |
| The processing of such a method is then essentially the same as if the return type of the method was an | |
| instance of the &jersey.server.mvc.Viewable; class. If a method is annotated with | |
| &lit.jersey.server.mvc.Template; and is also returning a | |
| &lit.jersey.server.mvc.Viewable; instance then the values from the | |
| &lit.jersey.server.mvc.Viewable; instance take precedence over those defined in the annotation. Producible | |
| media types are for both cases, &lit.jersey.server.mvc.Viewable; and &lit.jersey.server.mvc.Template;, | |
| determined by the method or class level &lit.jaxrs.Produces; annotation. | |
| </para> | |
| </section> | |
| <section> | |
| <title>Annotating Resource classes</title> | |
| <para> | |
| A resource class can have templates implicitly associated with it via &jersey.server.mvc.Template; annotation. | |
| For example, take a look at the resource class listing in <xref linkend="mvc.example.implicit.class"/>. | |
| <example xml:id="mvc.example.implicit.class"> | |
| <title>Using &lit.jersey.server.mvc.Template; on a resource class</title> | |
| <programlisting language="java">@Path("foo") | |
| @Template | |
| public class Foo { | |
| public String getFoo() { | |
| return "FOO"; | |
| } | |
| }</programlisting> | |
| </example> | |
| </para> | |
| <para> | |
| The example relies on Jersey MVC conventions a lot and requires more explanation as such. 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 &lit.jersey.server.mvc.Template; annotation placed on the resource class does not | |
| contain any information, the default relative template reference <literal>index</literal> will be used (for more | |
| on this topic see <xref linkend="mvc.references"/>). | |
| As for the missing resource methods, a default &lit.jaxrs.GET; method will be automatically generated by Jersey | |
| for the <literal>Foo</literal> resource (which is the MVC Controller now). The implementation of the generated | |
| resource method performs the equivalent of the following explicit resource method: | |
| <programlisting language="java">@GET | |
| public Viewable get() { | |
| return new Viewable("index", this); | |
| }</programlisting> | |
| You can see that the resource class serves in this case also as the model. Producible media types are determined | |
| based on the &lit.jaxrs.Produces; annotation declared on the resource class, if any. | |
| <note> | |
| <para> | |
| In case of "resource class"-based implicit MVC view templates, the controller is also the model. In such | |
| case the template reference <literal>index</literal> is special, it is the template reference | |
| associated with the controller instance itself. | |
| </para> | |
| </note> | |
| </para> | |
| <para> | |
| In the following example, the MVC controller represented by a JAX-RS &lit.jaxrs.GET; sub-resource method, | |
| is also generated in the resource class annotated with &lit.jersey.server.mvc.Template;: | |
| <programlisting language="java">@GET | |
| @Path("{implicit-view-path-parameter}") | |
| public Viewable get(@PathParameter("{implicit-view-path-parameter}") String template) { | |
| return new Viewable(template, this); | |
| }</programlisting> | |
| This allows Jersey to support also implicit sub-resource templates. For example, a JAX-RS resource at path | |
| <literal>foo/bar</literal> will try to use relative template reference <literal>bar</literal> that resolves to an | |
| absolute template reference <literal>/com/foo/Foo/bar</literal>. | |
| </para> | |
| <para> | |
| In other words, a HTTP &lit.http.GET; request to a <literal>/foo/bar</literal> would be handled by this | |
| auto-generated method in the <literal>Foo</literal> resource and would delegate the request to a registered | |
| template processor supports processing of the absolute template reference | |
| <literal>/com/foo/Foo/bar</literal>, where the model is still an instance of the same JAX-RS resource class | |
| <literal>Foo</literal>. | |
| </para> | |
| </section> | |
| </section> | |
| <section xml:id="mvc.references"> | |
| <title>Absolute vs. Relative template reference</title> | |
| <para> | |
| As discussed in the previous section, both &jersey.server.mvc.Template; and &jersey.server.mvc.Viewable; provide means | |
| to define a reference to a template. We will now discuss how these values are interpreted and how the concrete | |
| template is found. | |
| </para> | |
| <section> | |
| <title>Relative template reference</title> | |
| <para> | |
| Relative reference is any path that does not start with a leading '<literal>/</literal>' (slash) character (i.e. | |
| <literal>index.foo</literal>). This kind of references is resolved into absolute ones by pre-pending a given value | |
| with a fully qualified name of the last matched resource. | |
| </para> | |
| <para> | |
| Consider the <xref linkend="mvc.example.implicit.class">example</xref> from the previous section, | |
| the template name reference <literal>index</literal> is a relative value that Jersey will resolve to its | |
| absolute template reference using a fully qualified class name of <literal>Foo</literal> (more on resolving | |
| relative template name to the absolute one can be found in the JavaDoc of &jersey.server.mvc.Viewable; class), | |
| which, in our case, is: | |
| <programlisting language="java" linenumbering="unnumbered">"/com/foo/Foo/index"</programlisting> | |
| </para> | |
| <para> | |
| Jersey will then search all the registered template processors (see <xref linkend="mvc.spi"/>) 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. | |
| </para> | |
| <note> | |
| <para> | |
| If none or empty template reference is provided (either in &lit.jersey.server.mvc.Viewable; or via | |
| &lit.jersey.server.mvc.Template;) then the <literal>index</literal> reference is assumed and all further | |
| processing is done for this value. | |
| </para> | |
| </note> | |
| </section> | |
| <section> | |
| <title>Absolute template reference</title> | |
| <para> | |
| Let's change the resource &lit.http.GET; method in our <literal>Foo</literal> resource a little: | |
| <example xml:id="mvc.example.viewable.absolutePath"> | |
| <title>Using absolute path to template in &lit.jersey.server.mvc.Viewable;</title> | |
| <programlisting language="java">@GET | |
| public Viewable get() { | |
| return new Viewable("/index", "FOO"); | |
| }</programlisting> | |
| </example> | |
| In this case, since the template reference begins with <literal>"/"</literal>, 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. | |
| </para> | |
| <para> | |
| Absolute template references start with leading '<literal>/</literal>' (i.e. <literal>/com/example/index.foo</literal>) | |
| character and are not further resolved (with respect to the resolving resource class) which means that the | |
| template is looked for at the provided path directly. | |
| </para> | |
| <para> | |
| Note, however, that template processors for custom templating engines may modify (and the supported ones do) | |
| absolute template reference by pre-pending 'base template path' (if defined) and appending template suffix (i.e. | |
| <literal>foo</literal>) if the suffix is not provided in the reference. | |
| </para> | |
| <para> | |
| For example assume that we want to use Mustache templates for our views and we have defined 'base template path' | |
| as <literal>pages</literal>. For the absolute template reference <literal>/com/example/Foo/index</literal> the template | |
| processor will transform the reference into the following path: <literal>/pages/com/example/Foo/index.mustache</literal>. | |
| </para> | |
| </section> | |
| </section> | |
| <section> | |
| <title>Handling errors with MVC</title> | |
| <para> | |
| In addition to &jersey.server.mvc.Template; an &jersey.server.mvc.ErrorTemplate; annotation has been introduced in | |
| Jersey 2.3 (valid for Jersey 3.x as well). The purpose of this annotation is to bind the model to an error view in | |
| case an exception has been raised during processing of a request. This is true for any exception thrown after the | |
| resource matching phase (i.e. this not only applies to JAX-RS resources but providers and even Jersey runtime as | |
| well). The model in this case is the thrown exception itself. | |
| </para> | |
| <para> | |
| <xref linkend="mvc.example.error.simple"/> shows how to use &lit.jersey.server.mvc.ErrorTemplate; on a resource method. | |
| If all goes well with the method processing, then the <literal>/short-link</literal> template is used as page sent | |
| to the user. Otherwise if an exception is raised then the <literal>/error-form</literal> template is shown to the user. | |
| </para> | |
| <example xml:id="mvc.example.error.simple"> | |
| <title>Using &lit.jersey.server.mvc.ErrorTemplate; on a resource method</title> | |
| <programlisting language="java">@POST | |
| @Produces({"text/html”}) | |
| @Consumes(MediaType.APPLICATION_FORM_URLENCODED) | |
| @Template(name = "/short-link") | |
| @ErrorTemplate(name = "/error-form") | |
| public ShortenedLink createLink(@FormParam("link") final String link) { | |
| // ... | |
| }</programlisting> | |
| </example> | |
| <para> | |
| Note that &jersey.server.mvc.ErrorTemplate; can be used on a resource class or a resource method to merely handle | |
| error states. There is no need to use &jersey.server.mvc.Template; or &jersey.server.mvc.Viewable; with it. | |
| </para> | |
| <para> | |
| The annotation is handled by custom &jaxrs.ext.ExceptionMapper; which creates an instance of | |
| &lit.jersey.server.mvc.Viewable; that is further processed by Jersey. This exception mapper is registered automatically | |
| with a &lit.jersey.server.mvc.MvcFeature;. | |
| </para> | |
| <section> | |
| <title>MVC & Bean Validation</title> | |
| <para> | |
| &lit.jersey.server.mvc.ErrorTemplate; can also be used with Bean Validation to display specific error pages in | |
| case the validation of input/output values fails for some reason. Everything works as described above except the | |
| model is not the thrown exception but rather a list of &jersey.ext.ValidationError;s. This list can be iterated in | |
| the template and all the validation errors can be shown to the user in a desirable way. | |
| </para> | |
| <example xml:id="mvc.example.error.bv"> | |
| <title>Using &lit.jersey.server.mvc.ErrorTemplate; with Bean Validation</title> | |
| <programlisting language="java">@POST | |
| @Produces({"text/html”}) | |
| @Consumes(MediaType.APPLICATION_FORM_URLENCODED) | |
| @Template(name = "/short-link”) @ErrorTemplate(name = "/error-form") | |
| @Valid | |
| public ShortenedLink createLink(@NotEmpty @FormParam("link") final String link) { | |
| // ... | |
| }</programlisting> | |
| </example> | |
| <example xml:id="mvc.example.error.bv.jsp"> | |
| <title>Iterating through &lit.jersey.ext.ValidationError; in JSP</title> | |
| <programlisting language="xml"><![CDATA[<c:forEach items="${model}" var="error"> | |
| ${error.message} "<strong>${error.invalidValue}</strong>"<br/> | |
| </c:forEach>]]></programlisting> | |
| </example> | |
| <para> | |
| Support for Bean Validation in Jersey MVC Templates is provided by a <literal>jersey-mvc-bean-validation</literal> | |
| extension module. The JAX-RS &jaxrs.core.Feature; provided by this module | |
| (<literal>MvcBeanValidationFeature</literal>) has to be registered in order to use this | |
| functionality (see <xref linkend="mvc.registration"/>). | |
| </para> | |
| <para> | |
| Maven users can find this module at coordinates | |
| <programlisting language="xml"><dependency> | |
| <groupId>org.glassfish.jersey.ext</groupId> | |
| <artifactId>jersey-mvc-bean-validation</artifactId> | |
| <version>&version;</version> | |
| </dependency></programlisting> | |
| and for non-Maven users the list of dependencies is available at &jersey.ext.mvc-bean-validation.deps.link;. | |
| </para> | |
| </section> | |
| </section> | |
| <section xml:id="mvc.registration"> | |
| <title>Registration and Configuration</title> | |
| <para> | |
| To use the capabilities of Jersey MVC templating support in your JAX-RS/Jersey application you need to register | |
| specific JAX-RS &jaxrs.core.Feature;s provided by the MVC modules. For <literal>jersey-mvc</literal> module it is | |
| &jersey.server.mvc.MvcFeature; for others it could be, for example, &jersey.server.mvc.FreemarkerMvcFeature; | |
| (<literal>jersey-mvc-freemarker</literal>). | |
| <example> | |
| <title>Registering &lit.jersey.server.mvc.MvcFeature;</title> | |
| <programlisting language="java">new ResourceConfig() | |
| .register(org.glassfish.jersey.server.mvc.MvcFeature.class) | |
| // Further configuration of ResourceConfig. | |
| .register( ... );</programlisting> | |
| </example> | |
| <example> | |
| <title>Registering &lit.jersey.server.mvc.FreemarkerMvcFeature;</title> | |
| <programlisting language="java">new ResourceConfig() | |
| .register(org.glassfish.jersey.server.mvc.freemarker.FreemarkerMvcFeature.class) | |
| // Further configuration of ResourceConfig. | |
| .register( ... );</programlisting> | |
| </example> | |
| <note> | |
| <para> | |
| Modules that uses capabilities of the base Jersey MVC module register &lit.jersey.server.mvc.MvcFeature; | |
| automatically, so you don't need to register this feature explicitly in your code. | |
| </para> | |
| </note> | |
| </para> | |
| <para> | |
| Almost all of the MVC modules are further configurable and either contain a <literal>*Properties</literal> | |
| (e.g. <literal>FreemarkerMvcProperties</literal>) class describing all the available properties which could be | |
| set in a JAX-RS &lit.jaxrs.core.Application; / &lit.jersey.server.ResourceConfig;. Alternatively, the properties | |
| are listed directly in the module <literal>*Feature</literal> class. | |
| <example xml:id="mvc.ex.rc.properties"> | |
| <title>Setting <literal>MvcFeature.TEMPLATE_BASE_PATH</literal> value in &lit.jersey.server.ResourceConfig;</title> | |
| <programlisting language="java">new ResourceConfig() | |
| .property(MvcFeature.TEMPLATE_BASE_PATH, "templates") | |
| .register(MvcFeature.class) | |
| // Further configuration of ResourceConfig. | |
| .register( ... );</programlisting> | |
| </example> | |
| <example xml:id="mvc.ex.web.xml.properties"> | |
| <title>Setting <literal>FreemarkerMvcProperties.TEMPLATE_BASE_PATH</literal> value in <literal>web.xml</literal></title> | |
| <programlisting language="xml"><![CDATA[<servlet> | |
| <servlet-name>org.glassfish.jersey.examples.freemarker.MyApplication</servlet-name> | |
| <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> | |
| <init-param> | |
| <param-name>jakarta.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>]]></programlisting> | |
| </example> | |
| </para> | |
| </section> | |
| <section> | |
| <title>Supported templating engines</title> | |
| <para> | |
| Jersey provides extension modules that enable support for several templating engines. This section lists all the | |
| supported engines and their modules as well as discusses any module-specific details. | |
| </para> | |
| <section> | |
| <title>Mustache</title> | |
| <para> | |
| An integration module for <link xlink:href="https://github.com/spullara/mustache.java">Mustache</link>-based | |
| templating engine. | |
| </para> | |
| <para> | |
| Mustache template processor resolves absolute template references to processable template references represented | |
| as Mustache templates as follows: | |
| </para> | |
| <procedure> | |
| <title>Resolving Mustache template reference</title> | |
| <step> | |
| <para> | |
| if the absolute template reference does not end in <literal>.mustache</literal> append this suffix to the | |
| reference; and | |
| </para> | |
| </step> | |
| <step> | |
| <para> | |
| if <literal>ServletContext.getResource</literal>, <literal>Class.getResource</literal> or | |
| <literal>File.exists</literal> returns a non-&lit.null; value for the reference then | |
| return the reference as the processable template reference otherwise return &lit.null; | |
| (to indicate the absolute reference has not been resolved by the Mustache template processor). | |
| </para> | |
| </step> | |
| </procedure> | |
| <para> | |
| Thus the absolute template reference <literal>/com/foo/Foo/index</literal> would be resolved as | |
| <literal>/com/foo/Foo/index.mustache</literal>, provided there exists a | |
| <literal>/com/foo/Foo/index.mustache</literal> | |
| Mustache template in the application. | |
| </para> | |
| <para> | |
| Available configuration properties: | |
| <itemizedlist> | |
| <listitem> | |
| <para><literal>MustacheMvcFeature.TEMPLATE_BASE_PATH</literal> - | |
| <literal>jersey.config.server.mvc.templateBasePath.mustache</literal></para> | |
| <para>The base path where Mustache templates are located.</para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>MustacheMvcFeature.CACHE_TEMPLATES</literal> - | |
| <literal>jersey.config.server.mvc.caching.mustache</literal></para> | |
| <para>Enables caching of Mustache templates to avoid multiple compilation.</para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>MustacheMvcFeature.TEMPLATE_OBJECT_FACTORY</literal> - | |
| <literal>jersey.config.server.mvc.factory.mustache</literal></para> | |
| <para>Property used to pass user-configured <literal>MustacheFactory</literal>.</para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>MustacheMvcFeature.ENCODING</literal> - | |
| <literal>jersey.config.server.mvc.encoding.mustache</literal></para> | |
| <para>Property used to configure a default encoding that will be used | |
| if none is specified in &jaxrs.Produces; annotation. If property is not defined | |
| the UTF-8 encoding will be used as a default value.</para> | |
| </listitem> | |
| </itemizedlist> | |
| </para> | |
| <para> | |
| Maven users can find this module at coordinates | |
| <programlisting language="xml"><dependency> | |
| <groupId>org.glassfish.jersey.ext</groupId> | |
| <artifactId>jersey-mvc-mustache</artifactId> | |
| <version>&version;</version> | |
| </dependency></programlisting> | |
| and for non-Maven users the list of dependencies is available at &jersey.ext.mvc-mustache.deps.link;. | |
| </para> | |
| </section> | |
| <section> | |
| <title>Freemarker</title> | |
| <para> | |
| An integration module for <link xlink:href="https://freemarker.apache.org/">Freemarker</link>-based templating engine. | |
| </para> | |
| <para> | |
| Freemarker template processor resolves absolute template references to processable template references represented | |
| as Freemarker templates as follows: | |
| </para> | |
| <procedure> | |
| <title>Resolving Freemarker template reference</title> | |
| <step> | |
| <para> | |
| if the absolute template reference does not end in <literal>.ftl</literal> append this suffix to the | |
| reference; and | |
| </para> | |
| </step> | |
| <step> | |
| <para> | |
| if <literal>ServletContext.getResource</literal>, <literal>Class.getResource</literal> or | |
| <literal>File.exists</literal> returns a non-&lit.null; value for the reference then | |
| return the reference as the processable template reference otherwise return &lit.null; | |
| (to indicate the absolute reference has not been resolved by the Freemarker template processor). | |
| </para> | |
| </step> | |
| </procedure> | |
| <para> | |
| Thus the absolute template reference <literal>/com/foo/Foo/index</literal> would be resolved to | |
| <literal>/com/foo/Foo/index.ftl</literal>, provided there exists a <literal>/com/foo/Foo/index.ftl</literal> | |
| Freemarker template in the application. | |
| </para> | |
| <para> | |
| Jersey will assign the model instance to an attribute named <literal>model</literal>. | |
| So it is possible to reference the <literal>foo</literal> key from the provided <literal>Map</literal> (MVC Model) | |
| resource from the Freemarker template as follows: | |
| <programlisting language="xml" linenumbering="unnumbered"><![CDATA[<h1>${model.foo}</h1>]]></programlisting> | |
| </para> | |
| <para> | |
| Available configuration properties: | |
| <itemizedlist> | |
| <listitem> | |
| <para><literal>FreemarkerMvcFeature.TEMPLATE_BASE_PATH</literal> - | |
| <literal>jersey.config.server.mvc.templateBasePath.freemarker</literal></para> | |
| <para>The base path where Freemarker templates are located.</para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>FreemarkerMvcFeature.CACHE_TEMPLATES</literal> - | |
| <literal>jersey.config.server.mvc.caching.freemarker</literal></para> | |
| <para>Enables caching of Freemarker templates to avoid multiple compilation.</para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>FreemarkerMvcFeature.TEMPLATE_OBJECT_FACTORY</literal> - | |
| <literal>jersey.config.server.mvc.factory.freemarker</literal></para> | |
| <para>Property used to pass user-configured <literal>FreemarkerFactory</literal>.</para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>FreemarkerMvcFeature.ENCODING</literal> - | |
| <literal>jersey.config.server.mvc.encoding.freemarker</literal></para> | |
| <para>Property used to configure a default encoding that will be used | |
| if none is specified in &jaxrs.Produces; annotation. If property is not defined | |
| the UTF-8 encoding will be used as a default value.</para> | |
| </listitem> | |
| </itemizedlist> | |
| </para> | |
| <para> | |
| Maven users can find this module at coordinates | |
| <programlisting language="xml"><dependency> | |
| <groupId>org.glassfish.jersey.ext</groupId> | |
| <artifactId>jersey-mvc-freemarker</artifactId> | |
| <version>&version;</version> | |
| </dependency></programlisting> | |
| and for non-Maven users the list of dependencies is available at &jersey.ext.mvc-freemarker.deps.link;. | |
| </para> | |
| </section> | |
| <section> | |
| <title>JSP</title> | |
| <para> | |
| An integration module for JSP-based templating engine. | |
| </para> | |
| <important> | |
| <title>Limitations of Jersey JSP MVC Templates</title> | |
| <para> | |
| Jersey web applications that want to use JSP templating support should be registered as Servlet | |
| filters rather than Servlets in the application's <literal>web.xml</literal>. The | |
| <literal>web.xml</literal>-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. | |
| </para> | |
| </important> | |
| <para> | |
| JSP template processor resolves absolute template references to processable template references represented as JSP | |
| pages as follows: | |
| </para> | |
| <procedure> | |
| <title>Resolving JSP template reference</title> | |
| <step> | |
| <para> | |
| if the absolute template reference does not end in <literal>.jsp</literal> append this suffix to the | |
| reference; and | |
| </para> | |
| </step> | |
| <step> | |
| <para> | |
| if <literal>ServletContext.getResource</literal> returns a non-&lit.null; value for the reference then | |
| return the reference as the processable template reference otherwise return &lit.null; | |
| (to indicate the absolute reference has not been resolved by the JSP template processor). | |
| </para> | |
| </step> | |
| </procedure> | |
| <para> | |
| Thus the absolute template reference <literal>/com/foo/Foo/index</literal> would be resolved to | |
| <literal>/com/foo/Foo/index.jsp</literal>, provided there exists a <literal>/com/foo/Foo/index.jsp</literal> | |
| JSP page in the web application. | |
| </para> | |
| <para> | |
| Jersey will assign the model instance to the attribute named <literal>model</literal> or <literal>it</literal>. | |
| So it is possible to reference the <literal>foo</literal> property on the <literal>Foo</literal> resource | |
| from the JSP template as follows: | |
| <programlisting language="xml" linenumbering="unnumbered"><![CDATA[<h1>${model.foo}</h1>]]></programlisting> | |
| or | |
| <programlisting language="xml" linenumbering="unnumbered"><![CDATA[<h1>${it.foo}</h1>]]></programlisting> | |
| </para> | |
| <para> | |
| To include another JSP page in the currently processed one a custom <literal>include</literal> tag can be used. | |
| Mandatory parameter <literal>page</literal> represents a relative template name which would be absolutized using | |
| the same resolving resource class as the parent JSP page template. | |
| <example> | |
| <title>Including JSP page into JSP page</title> | |
| <programlisting language="xml"><![CDATA[<%@page contentType="text/html"%> | |
| <%@page pageEncoding="UTF-8"%> | |
| <%@taglib prefix="rbt" uri="urn:org:glassfish:jersey:servlet:mvc" %> | |
| <html> | |
| <body> | |
| <rbt:include page="include.jsp"/> | |
| </body> | |
| </html>]]></programlisting> | |
| </example> | |
| </para> | |
| <para> | |
| Available configuration properties: | |
| <itemizedlist> | |
| <listitem> | |
| <para><literal>JspMvcFeature.TEMPLATE_BASE_PATH</literal> - | |
| <literal>jersey.config.server.mvc.templateBasePath.jsp</literal></para> | |
| <para>The base path where JSP templates are located.</para> | |
| </listitem> | |
| </itemizedlist> | |
| </para> | |
| <para> | |
| Maven users can find this module at coordinates | |
| <programlisting language="xml"><dependency> | |
| <groupId>org.glassfish.jersey.ext</groupId> | |
| <artifactId>jersey-mvc-jsp</artifactId> | |
| <version>&version;</version> | |
| </dependency></programlisting> | |
| and for non-Maven users the list of dependencies is available at &jersey.ext.mvc-jsp.deps.link;. | |
| </para> | |
| </section> | |
| </section> | |
| <section xml:id="mvc.spi"> | |
| <title>Writing Custom Templating Engines</title> | |
| <para> | |
| To add support for other (custom) templating engines into Jersey MVC Templating facility, you need to implement the | |
| &jersey.server.mvc.TemplateProcessor; and register this class into your application. | |
| <tip> | |
| <para> | |
| When writing template processors it is recommend that you use an appropriate unique suffix for the | |
| processable template references, in which case it is then possible to easily support mixing of multiple | |
| templating engines in a single application without conflicts. | |
| </para> | |
| </tip> | |
| <example> | |
| <title>Custom &jersey.server.mvc.TemplateProcessor;</title> | |
| <programlisting language="java"><![CDATA[@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(); | |
| } | |
| }]]></programlisting> | |
| </example> | |
| <example> | |
| <title>Registering custom &jersey.server.mvc.TemplateProcessor;</title> | |
| <programlisting language="java">new ResourceConfig() | |
| .register(MyTemplateProcessor.class) | |
| // Further configuration of ResourceConfig. | |
| .register( ... );</programlisting> | |
| </example> | |
| </para> | |
| <note> | |
| <para> | |
| 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 &lit.pom.xml; file. | |
| </para> | |
| </note> | |
| <para> | |
| 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, | |
| you will need to add the base &jersey.ext.mvc.deps.link; module into the list of your dependencies: | |
| <programlisting language="xml"><dependency> | |
| <groupId>org.glassfish.jersey.ext</groupId> | |
| <artifactId>jersey-mvc</artifactId> | |
| <version>&version;</version> | |
| </dependency></programlisting> | |
| </para> | |
| </section> | |
| <section> | |
| <title>Other Examples</title> | |
| <para>To see an example of MVC (JSP) templating support in Jersey refer to the | |
| <link xlink:href='&jersey.github.examples.uri;/bookstore-webapp'>MVC (Bookstore) Example</link>.</para> | |
| </section> | |
| </chapter> |