Friday, 2 September 2011

Adding Sitemesh to your Spring webapp

The other day I came across a company that was recommending the use of Sitemesh as a way of creating re-useable JSP templates and this worried me slightly. There’s nothing particularly wrong with Sitemesh, it’s a tool for segmenting JSP pages in a similar way to Struts Tiles and it’s rather neat. The downside of using it is that it was written by the now defunct OpenSymphony, which means that no one’s supporting it and bugs, if there still are any, won’t get fixed. Furthermore, is the source code still available so that you can build it yourself? I also, wondered whether this company’s very prestigious clients know that this firm was using unsupported, vintage software and would they care?

So, whilst I can’t answer my second question, after doing some digging I did answer the first: SiteMesh can still be downloaded from https://java.net/downloads/sitemesh/ and this includes the source and some documentation. There is also a good introduction to Sitemesh available here: http://today.java.net/pub/a/today/2004/03/11/sitemesh.html. There is still another problem to consider: Sitemesh depends upon on a few other obsolete, elusive, vintage Jar files, in fact they were so elusive that I gave up searching for them.

If my site depended upon a host of unsupported obsolete products I'd be worried, but then perhaps I worry too much. So it's time to move on to the real purpose of this blog, which is to jot down a few notes of what you need to do to get vintage Sitemesh working in your application, which turns out to be pretty easy. The first step, after getting yourself a copy of SiteMesh, is to build it. This is easy: it’s an old fashioned Ant build. You can add the resulting sitemesh-2.x.x.jar file into your local Maven repository using:

mvn install:install-file -DgroupId=opensymphony -DartifactId=sitemesh -Dversion=2.2.4 -Dpackaging=jar -Dfile=<path to>/sitemesh-2.2.4/dist/sitemesh-2.2.4.jar

...but it's actually available from Maven Central.

Next you need a webapp to add Sitemesh to. For this demonstration I simply created a new Spring MVC webapp using Springsource’s STS and, once you’ve got a webapp, you need to add Sitemesh to you project’s POM file:

<!-- Sitemesh -->
  <dependency>
   <groupId>opensymphony</groupId>
   <artifactId>sitemesh</artifactId>
   <version>2.2.4</version>
  </dependency>

Now it’s time to start adding files and changing your code. Being seven or eight years old, Sitemesh is a lesson in configuration over convention; this is not a criticism, all frameworks were like that ‘back in the day’.

So, the first job is to add Sitemesh servlet filtering and taglib support to your web.xml:

<!-- Start of SiteMesh stuff -->    
 <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>  
 <!--  UPDATE updated this XML to match the latest servlet spec -->
 <jsp-config>    
  <taglib>
     <taglib-uri>sitemesh-page</taglib-uri>
     <taglib-location>/WEB-INF/sitemesh-page.tld</taglib-location>
  </taglib>    
  <taglib>
   <taglib-uri>sitemesh-decorator</taglib-uri>
      <taglib-location>/WEB-INF/sitemesh-decorator.tld</taglib-location>
  </taglib>    
 </jsp-config> 
 <!-- End of SiteMesh stuff -->    

The big idea behind Sitemesh is that your webapp’s output JSP is injected into a Sitemesh decorator JSP. This means that the Sitemesh decorator JSP provides the header and footer of your page, whilst your webapp concentrates on providing body content. To do this, you need some decorator JSP files, which are stored by convention in a /decorator folder. Below is an example page:

<%-- JSTL Java Server Pages Tag Library --%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--Sitemesh Decorator library --%>
<%@ taglib uri="sitemesh-decorator" prefix="decorator" %>
<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <title>
    My Site - <decorator:title default="The Main Page!" />
  </title>
    <link rel="stylesheet" href="<c:url value='/resources/style/simple.css'/>" type="text/css">
  
 </head>
  <decorator:head />
 <body>
 <div class="outline">
   <h1><decorator:title default="Welcome!" /></h1> 
   The Body Follows...
   <div class="outline"><decorator:body /></div>
   End of Body
   <p><small>
   (<a 
      href="?printable=true">printable version</a>)
      </small></p>
 </div>  
 </body>
</html>

You’ll notice that the sample above contains a few decorator tags with the main one being <decorator:body />. This specifies where you outgoing JSP will be injected into the decorator JSP. In order to get these working, I needed to add sitemesh-decorator.tld to my /WEB-INF directory.

The final step is to connect the decorator JSPs to your webapp via Sitemesh’s filter servlet. This is done by using a file with a default name of decorators.xml located in the WEB-INF directory.

<decorators defaultdir="/decorators">
 <decorator name="main" page="main.jsp">
 <pattern>*</pattern>
 </decorator>
 
 <decorator name="printable" page="printable.jsp"/>
</decorators>

This is a very straight forward chunk of XML, everything (as demonstrated by the ‘*’ pattern) is routed to main.jsp.

The image below shows the resulting Spring MVC webapp file structure:


That about completes this overview of adding Sitemesh to a Spring webapp though obviously, there are more features that may, or may not get a mention on some later date....

No comments: