Web View Templates with JSP ViewResolver(s)

Jorge Simão

Abstract

ViewResolver(s) are a common abstraction in request-driven MVC Web Framework to abstract and encapsulate the process by which a logical view name is mapped to physical view resource file. I propose the use of a type of ViewResolver, JspTemplateViewResolver, as a mean to automate the composition of web pages layout using plain-old JSP/JSTL views. JSP view templates use path expressions in include tags to insert pages main content in-place, composed with other shared layout components. The JspTemplateViewResolver generates View instances that contain information about the template, the main content, and title of the target view. Before performing the rendering of the template, the View sets request-scoped attributes that are used in EL-expression to resolved the location of the page's main content resource file and the title. The approach is shown to solve the problem of web page layout composition, without the need of external meta-data configuration files or a dedicated templating engine. I illustrate the approach first with a custom request-driven MVC web framework, and later I show how it can be applied to other frameworks such as Spring MVC.

Keywords: JSP View Layout Templates, JspTemplateViewResolver, Request-Driven MVC Web Framework, Spring MVC, Template Engine

Introduction

Composing web pages with templates is a common approach to simplify the task of providing a consistent look-and-feel in a web-site. Elsewhere, I showed how JSP templates can be used to compose pages using the composite design-pattern. JSP template pages use a <jsp:include> tag (or alternatively, the <%@include%> directive), to include the main content of each page. This is made to work because the included resource is not statically specified, but is the result of evaluating an EL expression like ${main}. The variable main is set to the location of the page's main content file. Each time the template view is rendered the page's specific main content of pages is inserted in-place. Similar approach can be used to other page specific elements, such as title strings.

When all resources in a web application are JSP pages, setting the value of the variable (main) need to be done, necessarily, in JSP. In the simplest approach, an additional JSP page is needed for each end-user page. Thus a site with N end-user pages, would required 2N JSP pages (plus the template page and shared component pages such as header, footer, and navigation page). A more parsimonious approach, is to have a single master JSP page that sets the main variable based on some external value, such HTTP parameter.

When web applications use Java resources, such as Servlets or controllers of a request-driven MVC web framework, the task of setting the main variable does not need to be done by JSP pages. If the processing of requests goes first through a Servlet, some method or component in Java can set the main variable appropriately. This greatly simplifies application development, since the web-developers needs to provide only the N JSP files for the main content of end-user pages (plus the JSP files for the view template and the shared components).

ViewResolvers are a common abstraction in request-driven MVC web framework to abstract the process of mapping the logical name of a view, to a View instance set with the physical location of the respective resource file. Often, a ViewResolver uses a rule to build the location of the view to render, such as adding a base location prefix and adding a default file extension. Having View instances render directly page's main content resource file, makes it difficult to use view templates. Two work around are possible: the decoration of the view is done at a later phase, such as in an additional Filter; alternatively, the template view is rendered first, and the main content of the page is rendered in-place.

In this article, I show how to implement a ViewResolver(s) that render pages fully composed with template markup. The approach followed by these designated JspTemplateViewResolver(s), is to create Views instances that always start by rendering the template view. In addition to take, a request-scoped attribute is set with the value of the main content page. This is the value built from the return value of the MVC handler methods. The combination of these two techniques allows view templates to insert page's main content in-place. Similar technique can be applied to other page specific information, such as page title.

The JspTemplateViewResolver abstraction allows to solve the problem of dynamic web page composition based on the decorator design-pattern. This means that there is no need for external meta-data information to compose pages -- such as XML view definition files (e.g. as done in Apache Tiles view templating engine), or explicitly composing page markup on a per-page basis (such as can be done in Apache Tiles, and in JSF/Facelets templating component libraries). The approach also more efficient than implementation of the decorator design-pattern based on Filters (e.g. as done in SiteMesh), because pages do not have to be read, parsed, and written to an output stream twice.

The rest of the article is organized as follow: first, I show a sample view template as an example of what should be provided by a web-developer. Next, I review the concept of ViewResolver and View abstractions as commonly used in request-driven MVC frameworks. The concrete implementation of these abstractions for rendering JSP pages is illustrated next. This implementation is then extended to support JSP templates. I show-case the approach first in the context of a custom MVC framework, and in a later section is adapted to the widely used Spring MVC framework. I conclude the article by comparing the approach with others, and presenting the conclusions.

Sample Application

For the purpose of illustrating the techniques presented in this article I use a simple demo application, consisting of a template JSP page, a servlet running as web layer controller, two JSP web pages, and a property file.

Sample JSP Template

View templating involves defining one or more templates to decorate or compose web pages. In the approach outlined in this article, I use plain JSP/JSTL pages to define templates. The key characteristic of these templates is that the page's main content is inserted with an element like <jsp:include page="$main" />.

Below, I show an example of a JSP template following this approach:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<fmt:setBundle basename="titles" var="titlesBundle" />

<title><fmt:message key="${title}" bundle="${titlesBundle}"/></title>
 
<c:url value="/style/myapp.css" var="myappCss"/>
<link href="${myappCss}" rel="stylesheet" type="text/css">

</head>
<body>

<jsp:include page="common/header.jsp" />

<jsp:include page="${main}" />

<jsp:include page="common/footer.jsp" />

</body>
</html>

The template page assumes that a request-scoped attribute (variable) named main as been set by the MVC framework, before the template is rendered. Likewise, the title of the page the template will be rendered with is defined by variable title. The value of variable title is to be used as a message key to be resolved in a message bundle. This allow the title to be page specific, like the main content. Moreover, it allow the title to be localized.

A resource bundle is usually defined by one or more Java property files. In the demo template JSP page above, I use a dedicate resource bundle for titles. The JSTL tag <fmt:message key="title" bundle="titlesBundle"/> resolve the title key in the title resource bundle. The resource bundle variable named titlesBundle is set with JSTL tag <fmt:setBundle basename="titles" var="titlesBundle" />

Below, I show the content of the file titles.properties used for testing:

view.title.account.list=Account List
view.title.account.show=Account Details 

Sample Servlet/Controller

To actually generate a fully composed view, I need a web controller or servlet that takes care of selecting the view to render -- usually by having a handler method returning a string with the name of the view. Below, I show (partially) an example of a web layer component (controller) used to implement CRUD operations on domain object of type Account. It is implemented as an HttpServlet, but uses the support of a servlet class ReflectiveDispatcherServlet provided by a custom MVC framework.

@WebServlet({"/account", "/account/*", "/accounts","/accounts/*"})
public class AccountServlet extends ReflectiveDispatcherServlet {
	@Inject AccountDao accountDao;	
	
    public AccountServlet() {
		setViewResolver(new JspTemplateViewResolver("layout/standard"));
    }
   
	String list(Model model) {
		List<Account> accountList = accountDao.findAll();
		model.addAttribute("accounts", accountList);
		return "account/list";
	}
	
	String show(@HttpParam("id") Long id, Model model) {
		Account account = accountDao.get(id);
		model.addAttribute(account);
		return "account/show";
	}
	...
}

AccountServlet is being defined and deployed declaratively by using annotation @WebServlet (introduced with Servlet specification 3.0). The JEE6/CDI (JSR-299/JSR-330) annotation @Inject is also used to perform dependency injection on the servlet to get a referenced to the Account repository AccountDao.

The application defined methods of AccountServlet are invoked reflectively by the support servlet ReflectiveDispatcherServlet. Each method return a string that is interpreted as a view name.

An example of a URL exposed by this servlet is: http://localhost:8080/accounts/show?id=123

In the constructor of the servlet, some configuration is done. Namely, a ViewResolver is set so that the pages are rendered using the specified template. This is discussed next.

The ViewResolver and View Abstraction

A ViewResolver is an abstraction used in request-driven web MVC frameworks to map logical view names to actual view resources. To allow multiple view technologies to be used within the same application and MVC framework, the additional abstraction View is also introduce. View instances encapsulate the actual rendering of the view resource to the response output stream, using some rendering technology.

Handler methods of web-layer components (controllers) built in the application take the responsibility of selecting the logical name of the views to render. For this logical view name, a ViewResolver creates a View instance and configured it appropriately.

Below, we show an example specification for a ViewResolver. The method resolve() defines the mapping of a logical view name to a concrete View object.

public interface ViewResolver {
	View resolve(String viewName);
}

The specification for the View is also shown below. The method render() is used to write the view content to the output stream associated with a particular HTTP request/response.

public interface View {
	void render(Model model, Locale locale, HttpServletRequest request,
				HttpServletResponse response) throws ServletException, IOException;
}

Rendering JSP with ViewResolvers

JSP is one particular way to define and render views. The Servlet standard (JSR-315) defines the away by which JSP view can be rendered from Java code. Thus, we can easy develop an implementation of a ViewResolver and View to work with JSP.

Below, we show a possible implementation for a JspViewResolver that maps logical view names to physical resource location by adding a file prefix and suffix. It generates instances of JspView, that do the actual work of rendering the JSP pages to the output stream.

public class JspViewResolver implements ViewResolver {
	protected String prefix = "/WEB-INF/views/";
	protected String suffix = ".jsp";
	protected String root = "";

	public JspViewResolver() {
	}


	//other constructors
	//...

	//property setters and getters for prefix, suffix, and root
	
	@Override
	public View resolve(String viewName) {
		return new JspView(getViewResource(viewName));
	}

	public String getViewResource(String viewName) {
		return root + prefix + viewName + suffix;
	}
}

Below, we see the actual code of the JspView. Method render() uses the standard approach defined by the Servlet API to render a JSP view -- by forward the request to RequestDispatcher associated with the view resource file.

public class JspView implements View {
	protected String path;
	
	public JspView(String path) {
		this.path = path;
	}

	//setter and getter for property: path
	//...
	
	@Override
	public void render(Model model, Locale locale, HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		RequestDispatcher dispatcher = request.getServletContext().getRequestDispatcher(path);
		dispatcher.forward(request, response);
	}
}

ViewResolvers for JSP View Templates

Your goal is to extend the implementation of the JspViewResolver and JspView to support JSP templates.

Implementing a JspTemplateViewResolver

Below, I show the implementation of class JspTemplateViewResolver that extends directly JspViewResolver. It takes as constructor argument the name of the JSP template file that is used to decorate other JSP pages. JspTemplateViewResolver.resolve() method works similar to its parent class, except that the created views are of a different type. This views, of type DecoratedJspView, are passed three constructor arguments: the template file location, the specific resource file to be used as the page main content, and a message key for the title of the page.

public class JspTemplateViewResolver extends JspViewResolver {
	protected String templateName;
	
	public JspTemplateViewResolver(String templateName) {
		this.templateName = templateName;
	}

	//other constructors
	//...

	@Override
	public View resolve(String viewName) {
		return new JspTemplateView(getViewResource(templateName), getViewResource(viewName), getTitle(viewName));
	}

	protected String getTitle(String viewName) {
		return "view.title." + preprocessViewName(viewName).replace('/', '.');
	}
	
	protected String preprocessViewName(String viewName) {
		int i= viewName.indexOf('?');
		return i>0 ? viewName.substring(0,i) : viewName;
	}	
}

For the page title we use a message key prefixed by view.title. and concatenated with the logical view name (with slash characters replaced by dots). Care is taken so that the view name is pre-processed to remove the query string. For example, if the logical name of a view is account/show?id=1, the the key for the title is "view.title.account.show".

Implementing the DecoratedJspView

The DecoratedJspView class is where the actual work of implementing the templating solution is done. The implementation is shown below:

public class DecoratedJspView extends JspView {
	protected String viewPath;
	protected String title;
		
	public DecoratedJspView(String templatePath, String viewPath, String title) {
		super(templatePath);
		this.viewPath = viewPath;
		this.title = title;
	}
	
	//property setters and getters for viewPath and title
	//...
	
	@Override
	public void render(Model model, Locale locale, HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		request.setAttribute("main", viewPath);
		request.setAttribute("title", title);		
		super.render(model, locale, request, response);
	}

}

Notice that DecoratedJspView extends JspView, and always renders the template JSP file first. This is ensured by calling super(templatePath). This solution may look a bit "surprising", because after we ought to be rendering the page specific content. This is, however, taken care of in method render() by setting the value of the request scoped attribute with name main -- which is the variable name used in the template element <jsp:include page="$main" /> - to have the location of the page main content. This allows the template to included the page specific content as required. In addition to that, another request scoped attribute with name title is set with the title value provided by JspTemplateViewResolver.

Because the all purpose of having templates is to decorate multiple pages.

Porting JspTemplateViewResolver to Spring MVC

The approach outline above for web templates based on a JspTemplateViewResolver is quite general, and can be used in any Servlet based application and/or request-driven MVC web framework. Spring MVC is one such web frameworks. Because Spring MVC has its own abstractions for ViewResolver and View, the best "porting" strategy it to extends this abstractions directly (rather than reuse the code previously shown for the custom MVC framework).

Review of Spring MVC Abstractions and Configuration

In Spring MVC, JSP pages are commonly rendered using an implementation of an InternalResourceViewResolver (or TilesViewResolver), that implement (indirectly) the interface ViewResolver. Internally, InternalResourceViewResolver creates a views of type InternalResourceView, or JstlView, if JSTL JARs are found in the classpath. These View types use the standard RequestDispatcher associated with the target page and forward the request to it (essentially, using the same approach that I sketched above). JstlView also sets up the i18n context by making messages defined in configured MessageSource available for resolution.

InternalResourceViewResolver is usually configured in a bean definition file configured for the Spring MVC DispatcherServlet. It is commonly configured with a naming resolution strategy based on path prefix and suffix. Below, we show a typical configuration:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="/WEB-INF/views/" />
  <property name="suffix" value=".jsp" />
</bean> 

Implementing a JspTemplateViewResolver for Spring MVC

To bring JSP templates to Spring MVC, I make the a custom class JspTemplateViewResolver to extend InternalResourceViewResolver. Additionally, I implement two custom View classes, DecoratedInternalResourceView and DecoratedJstlView that extend, respectively, the Spring MVC classes InternalResourceView and JstlView.

Below, we show the code for JspTemplateViewResolver:

package org.helloapp.spring.web.view.jsp;

import org.springframework.util.ClassUtils;
import org.springframework.web.servlet.view.*;

public class JspTemplateViewResolver extends InternalResourceViewResolver {

	private static final boolean jstlPresent = ClassUtils.isPresent(
			"javax.servlet.jsp.jstl.core.Config",
			InternalResourceViewResolver.class.getClassLoader());

	protected String templateName;
	
	public JspTemplateViewResolver(String templateName) {
		this.templateName = templateName;
		Class<?> viewClass = jstlPresent ? DecoratedJstlView.class : DecoratedInternalResourceView.class;
		setViewClass(viewClass);
	}
	
	public JspTemplateViewResolver() {
		this(null);
	}
	
	//property setter and getter for templateName
	//...	
	

	@Override
	protected AbstractUrlBasedView buildView(String viewName) throws Exception {
		TemplateView view = (TemplateView) super.buildView(viewName);
		String templatePath = getPrefix() + templateName + getSuffix();
		view.setTemplatePath(templatePath);
		view.setTitle(getTitle(viewName));
		return (AbstractUrlBasedView)view;
	}
	
	protected String getTitle(String viewName) { ... }

}

By taking a quick look at the source code of InternalResourceViewResolver, we can find the implementation code for the condition that determining which View type to created. This is coded in the value expression for static field jstlPresent. If jstlPresent==true the view class to DecoratedJstlTemplate is used, otherwise, it falls-back to DecoratedInternalResourceView. This is done to mirror the way views are created and used in the Spring MVC InternalResourceViewResolver.

The constructor for JspTemplateViewResolver takes as parameter the name of the template to decorate pages. A corresponding property setter and getter is also available, to support different styles of configuration.

The buildView() method is where the View instance is actually created. The implementation of JspTemplateViewResolver.buildView() delegates most of the work to the parent class. In addition to that, it configures the created View instances to use the configured template. This is done by calling property setter setTemplatePath(). In addition to that, the property setter setTitle() is used to set the value of the the message key for the view title. The implementation for JspTemplateViewResolver.getTitle() is identical to the one we presented earlier for the custom MVC framework.

Because, the JspTemplateViewResolver.buildView() method needs to deal with two types of View, I defined the interface TemplateView that is implemented the both types of Views. The specification of this interface is shown below:

public interface TemplateView {
	void setTemplatePath(String templateName);
	void setTitle(String title);
}

Note that the template resource files are assumed to be located in the same directory tree as the main content pages. This means that the same path prefix and suffix can be used to build both the path of the template file and the path of page's main content files.

Decorated View Implementations for Spring MVC

The code below show the implementation of the DecoratedInternalResourceView. To ensure maximum consistency and portability, it extends the Spring MVC InternalResourceView. The property templatePath holds the file location of the template file to be used to decorate the web page, as set by JspTemplateViewResolver.

public class DecoratedInternalResourceView extends InternalResourceView implements TemplateView {
	protected String templatePath;
	protected String title;

	public DecoratedJspView() {
	}

	//setters and getters for properties templatePath and title
	//...
	
	@Override
	protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
		model.put("main", getUrl());
		model.put("title", title);		
		super.renderMergedOutputModel(model, request, response);
	}

	protected String prepareForRendering(HttpServletRequest request, HttpServletResponse response) throws Exception {
		return templatePath;
	}
	
}

DecoratedInternalResourceView needs to perform two tasks. First, it needs to make sure that the first view to be rendered is the template, rather then the page's main content file. This is done by overriding the method prepareForRendering, which is defined in the parent class InternalResourceView as hook for customization. The second task of DecoratedInternalResourceView is to set the request-scoped attribute main to the location of the page's main content resource file. This is done in method renderMergedOutputModel(), by adding an attribute named main to the model object associated with the request. The value for main content file is obtained by calling getUrl(). Likewise, the message key for the title of the page is set in a model attribute named title. Because, all model attributes are eventually mapped to request scoped attributes, this does what we want. The overall solution integrates nicely and in a seemly away with Spring MVC.

The implementation for DecoratedJstlView is identical to the one outlined above for DecoratedInternalResourceView except that the parent class is JstlView.

public class DecoratedJstlView extends JstlView implements TemplateView {

  //Similar code to JspView
  //...
	
}

Configuring a JspTemplateViewResolver for Spring MVC

We can use the JspTemplateViewResolver has a replacement for the Spring MVC provided JspInternalViewResolver (and TilesViewResolver). Because JspTemplateViewResolver extends InternalViewResolver the same bean properties are available. In addition to that, JspTemplateViewResolver is further configured with a constructor argument and a property for the name of the template to use.

Below, I show a typical configuration of JspTemplateViewResolver. The template file is assumed to be located in path /WEB-INF/views/layout/standard.jsp.

<bean class="org.helloapp.spring.web.view.jsp.JspTemplateViewResolver">
  <constructor-arg value="layout/standard"/>
  <property name="prefix" value="/WEB-INF/views/" />
  <property name="suffix" value=".jsp" />
</bean>

An alternative configuration would be to set the template name as a property rather than a constructor argument, as shown below:

<bean class="org.helloapp.spring.web.view.jsp.JspTemplateViewResolver">
  <property name="templateName" value="layout/standard"/>
  <property name="prefix" value="/WEB-INF/views/" />
  <property name="suffix" value=".jsp" />
</bean>

Discussion and Comparison to Other Approaches

The JspTemplateViewResolver abstraction has been shown to be a viable solution to the problem of automatic view decoration based on templates for web application. Templates can be written as common JSP pages that follow a particular convention to insert the page's main content and title. Because, the selection of the main content view is done by web controllers (or servlet), there is not need to have additional JSP files or view definition files to provide page specific information. In this approach, the first view to be rendered is always the template view. Therefore there is not need to read, parse, and write twice the same view's markup. This approach contrasts with other pervasive solutions to web templating.

In Apache Tiles templating system, individual views can be composed by explicit composition (using the composite design-pattern) or, alternatively, by providing view definition files written in a custom XML language -- often saved with filename tiles.xml. In Tiles, view definition files provide information about which resource files to use to compose each individual view. While this view definition files are not a particularly hard thing to write, it requires management of extra project artifacts which reduces productivity. Namely, every time a new view is added to the project corresponding XML element(s) needs to be added to a view definition file, and in some cases it requires the creation of a new file. Moreover, Tiles logical view names are conceptually independent of the actual resource names. So while they are often syntactically similar, in some cases the developer might need to managed and remember additional names.

JSF, the Java standard web framework, also supports templates and view composition. This is done by using a Facelets taglib that supports templates based on the composition design-pattern. Namely, templates view use <ui:insert> tags to insert page specific content. Individual pages use tag <ui:composition> or <ui:decorate> to refer a template, with page specific content provided with tag <ui:define>. JSF approach partially mimics the Tiles approach in terms of explicitly composing pages. JSF does not, however, support the notion of view definition files as Tiles does. It does not support automated decoration either.

In the approach I presented in this article, there is no need to use external view definition files (written in XML or some other file format). The view is fully defined by providing the logical name of the page's main content resource file (in combination with the common template file). Explicit composition of the view is also not required, as the approach is better characterized as fitting the decorator design-pattern approach.

SiteMesh is another popular web templating framework based on decorator design-pattern. It is implemented as a Filter that reprocesses pages to perform the decoration. The template page is rendered by the Filter to the output stream, and the view written by the application to a temporary response stream is inserted at a particular point in the template by being rewritten to the response output stream. Filter based approach, as done in SiteMesh, have the inherent problem of extra performance costs. The main content file needs to (partially) read, parsed, and written twice to one or output stream. Apaches Tiles can also be configured as a Filter to implement the decorator design-pattern. The same performance issues are applicable to Tiles.

The approach based on the JspTemplateViewResolver has all the advantages of the decorator design-pattern, without performance costs. Namely, pages do not to be explicitly composed case-by-case, and there is not need to provide extra view definition meta-data. In contrast with implementations based on Filter, the page's main content resource files do not need to be process twice. This is accomplished because the templating mechanisms are fully integrated with the standard JSP page rendering life-cycle.

Summary and Conclusions

I have shown how the problem of automated decoration of web pages with template content can be solved in request-driven MVC frameworks. This involves a two-part solution: first, templates are designed to include page's main content; and, secondly, a JspTemplateViewResolver, implementing the interface ViewResolver, takes care of preparing the environment for rendering of the template.

Template views are written as common JSP pages that insert the target page main content using the standard element <jsp:include>. The location of the page's main content JSP file, is stored in a (request-scoped) attribute with some well-know name -- such as $main. Thus, the include statement takes the form of <jsp:include page="$main" />. A JspTemplateViewResolver is used to generate View instances that render first the template resource. View instances take the responsibility of setting the value of the (request scoped) attribute main. Pages specific title can be treated in a similar manner.

I have shown that the approach is quite generic, and can be used in a custom MVC framework and in other frameworks, such as Spring MVC. The Spring MVC implementation of JspTemplateViewResolver highlighted the simplicity to which such feature can be integrated in a seemly away. JspTemplateViewResolver can be used as a drop-in replacement to Spring MVC InternalResourceViewResolver or TilesViewResolver.

Overall, the approach presented in this article as shown that, for many projects, the use of dedicated view templating technology can be made redundant. The web templating problem can be solved using the basic technologies already in place for JSP view rendering and request dispatching.

Exercises to the Reader

Below, I present some suggestions to possible extensions to the JspTemplateViewResolver and/or the overall approach. The reader may find useful or instructive to work on these extensions, specially to address particular application needs. The proposed extensions can be done for a custom web framework, for Spring MVC, or other frameworks.

  • Several hard-coded constants and conventions were used in the implementation, such as: the name main and title, as variables for the location of the page's main content file and title; and the prefix view.title. for the message key of titles. Change the implementation of JspTemplateViewResolver to allow customization of this conventions.
  • Modify or extend the implementation of the JspTemplateViewResolver to support more than one template. A property named templateMap of type java.util.Map<String,String> should be used to map request URL to template names. The method HttpServletRequest.getPathInfo() should be used as a key to the map. The value is the name of the template to use. An additional property defaultTemplate should be used as a fallback template, for request paths not present in the map.
  • Improve the previous extension, so that the keys in templateMap can be set as URL patterns based on regular expressions.
  • Further improve the previous extensions, so that the keys can also by Ant-style path expression with wild-cards such as account/*, or product/*. Considerer the two implementation options: import the Ant-tool library for matching the path expression, and/or implement your own (simplified version) of the path expressions matching algorithm.
  • Modify the implementation(s) of JspTemplateViewResolver, DecoratedInternalResourceView and DecoratedJstlView, to allow the configurations of conventions to be done on a per-template basis.
  • Extend or Modify the JspTemplateViewResolver to support partial rending. When the Http request parameter fragment as value main, JspTemplateViewResolver should fallback to the behavior of InternalResourceViewResolver so that the template is not used to decorate the page, and only the main content page is sent to the client.
  • Spring MVC uses an abstraction of its own to represent resource bundles -- MessageBundle. Study this abstraction and its implementations, and confirm that the titles of pages can also be provided in property files configured with a MessageBundle.
  • Allow for handler methods to specify which template to use, by specifying view names with syntax templateName;viewName, or another equivalent syntax. Change the implementation of the JspTemplateViewResolver to support this.

Resources

Software Resources

External References

Acknowledgements

If you have any comments or suggestions that you think may improve this document please send an e-mail to the author.

Sponsors (contact to be a sponsor)
(c) Jorge Simão, 2013