Do you have a Java webapp that is showing it’s age and the layout and look-and-feel is just unmanageable? Maybe well-intentioned developers tried to reuse page chunks like the header and the footer and sidebars when they developed on your application originally in 2002 by using JSP includes … but now, after years of tweaks and additions here and there, making any non-trivial visual change to your application is a nightmare…
There are several templating solutions available for Java web applications. In a lot of scenarios, a good option is SiteMesh from OpenSymphony.
According to the SiteMesh site:
- SiteMesh is a web-page layout and decoration framework and web- application integration framework to aid in creating large sites consisting of many pages for which a consistent look/feel, navigation and layout scheme is required.
- SiteMesh intercepts requests to any static or dynamically generated HTML page requested through the web-server, parses the page, obtains properties and data from the content and generates an appropriate final page with modifications to the original. This is based upon the well-known Gang Of Four Decorator design pattern.
- SiteMesh can also include entire HTML pages as a Panel within another page. This is similar to a Server-Side Include, except that the HTML document will be modified to create a visual window (using the document’s Meta-data as an aid) within a page. Using this feature, Portal type web sites can be built very quickly and effectively. This is based upon the well-known GangOfFour Composite design pattern.
- SiteMesh is very extensible and is designed in a way in which it is easy to extend for custom needs.
Here’s what some JSP code for an item detail page looked like in my old Amazon affiliate site that I created in 2003:
<%@ include file="jspf/header.jspf" %>
<jsp:useBean id="results"
scope="request"
type="com.zabada.amazon.ListResults"/>
<jsp:useBean id="title" scope="request" type="java.lang.String"/>
<html>
<head>
<title><c:out value="${title}"/></title>
<%@ include file="/jspf/non-title-head-metadata.jspf" %>
</head>
<body>
<div id="header">
<%@ include file="/jspf/search-controls.jspf" %>
</div>
... MAIN CONTENT ...
</body>
</html>
The main thing that we want to do is eliminate the redundant includes and other repeated navigation in all our JSP files so that we can manage the headers, footers and navigation in one place.
So here’s what you’ve got to do to refactor your app to use SiteMesh …
Step 1 – Get SiteMesh and add it to your project
If you are using Maven, just add the following dependency to your web project:
<dependency> <groupId>opensymphony</groupId> <artifactId>sitemesh</artifactId> <version>2.3</version> </dependency>
Non-Maven users, download the SiteMesh distribution, and wire up your build so that the sitemesh-VERSION.jar file ends up in your webapp’s WEB-INF/lib directory.
Step 2 – Wire Up SiteMesh in your application’s web.xml
Add the following filters to your <web-app /> in the web.xml file:
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>
com.opensymphony.module.sitemesh.filter.PageFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Step 3 – Add the decorators.xml file to your WEB-INF
Create a new file called decorators.xml in your WEB-INF directory with the following contents:
<?xml version="1.0" encoding="ISO-8859-1"?>
<decorators defaultdir="/WEB-INF/decorators">
<decorator name="main" page="main.jsp">
<pattern>/*</pattern>
</decorator>
</decorators>
Step 4 – Create Main JSP Decorator File
Create a folder named decorators in your WEB-INF directory.
In that directory create a file named main.jsp. In main.jsp add a simple decorator like this:
<%@ taglib
prefix="decorator"
uri="http://www.opensymphony.com/sitemesh/decorator" %>
<html>
<head>
<title>
<decorator:getProperty property="title" default="Your Title"/>
</title>
<decorator:head/>
</head>
<body>
<h1>Sample Header</h1>
<decorator:body/>
<p>
<strong>Sample Footer</strong>
</p>
</body>
</html>
Timeout
Now, everything should be in place for the basics of getting SiteMesh up and running.
Deploy and startup your application and there should now be a header of “Sample Header” and footer of “Sample Footer” on all rendered pages.
In the previous step, our simple template does three simple things before the rendered page is sent to the browser:
- The body of the original non-decorated view is stripped and stuffed into the place where the <decorator:body/> tag is in our main.jsp template
- The content from the head of the non-decorated view is stuffed into the head of our newly decorated view
- If there was a title on the original non-decorated view, it is stuffed into the title tags in our newly decorated view, otherwise the title “Your Title” used.
And then the newly decorated page is sent to the browser. In this case, essentially all that is happening is that the page is re-rendered with our silly “Sample Header” stuffed above our content in an h2 and the text “Sample Footer” is stuffed below the content in a paragraph tag.
Really, that’s all there is to basic usage of SiteMesh. Obviously you’d want to work your main.jsp template to show your actual applications header, navigations panels, etc.
So …
Step 5 – Edit Your Main Decorator
Edit your main.jsp to include your common header, footer navigation, etc.
And finally …
Step 6 – Refactor Your Views
Strip out all of your redundant header and footer and navigation gunk from your views.
Really, that’s it for the basics.
Clearly your real project will be a little more involved.
- There may be alternate decorators to add for different kinds of views. Particularly pop-up windows or other alternate views that you application presents.
- You may have to add some fanciness to your main decorator to be context sensitive to help the decorator display breadcrumbs, “where-you-are” indicators in the navigation, etc.
For further help, the following SiteMesh documents are helpful:
Now get to cleaning up your crusty old views!