Overview
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.
Integrating WebWork with SiteMesh is amazingly simple: you don't have to do anything in fact. WebWork stores all its value stack information in the request attributes, meaning that if you wish to display data that is in the stack (or even the ActionContext) you can do so by using the normal tag libraries that come with WebWork. That's it!
ActionContextCleanUp
In WebWork's Architecture, the standard filter-chain optionally starts with the ActionContextCleanUp filter, followed by other desired filters. Lastly, the FilterDispatcher handles the request, usually passing it on to the ActionMapper. The primary purpose of the ActionContextCleanUp is for SiteMesh integration. This tells the FilterDispatcher when exactly, to clean-up the request. Otherwise, the ActionContext may be removed before the decorator attempts to access it.
 | Warning If ActionContext access is required within the decorators, the ActionContextCleanUp filter must be placed at the beginning of the filter-chain. |
For more information, see the javadocs of the ActionContextCleanUp filter:
Special filter designed to work with the FilterDispatcher and allow
for easier integration with SiteMesh. Normally, ordering your filters to have
SiteMesh go first, and then FilterDispatcher go second is perfectly fine.
However, sometimes you may wish to access WebWork-features, including the
value stack, from within your SiteMesh decorators. Because FilterDispatcher
cleans up the ActionContext, your decorator won't have access to the
date you want.
By adding this filter, the FilterDispatcher will know to not clean up and
instead defer cleanup to this filter. The ordering of the filters should then be:
- this filter
- SiteMesh filter
- FilterDispatcher
Velocity and FreeMarker Decorators
WebWork provides extension of the SiteMesh PageFilter that assist with integration with Velocity and FreeMarker. We strongly recommend using these filters, instead of the support provided by SiteMesh, because they also will provide the standard variables and Tags that you are used to when created views in your favoriate template language.
Velocity
If you are using Velocity for your SiteMesh decorators, we recommend using the VelocityPageFilter. This is an extension of the SiteMesh PageFilter, which should be placed in the web.xml in between the ActionContextCleanUp and the FilterDispatcher. Now the Velocity decorators will have access to WebWork variables such as $stack and $request.
<filter>
<filter-name>webwork-cleanup</filter-name>
<filter-class>com.opensymphony.webwork.dispatcher.ActionContextCleanUp</filter-class>
</filter>
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.webwork.sitemesh.VelocityPageFilter</filter-class>
</filter>
<filter>
<filter-name>webwork</filter-name>
<filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>webwork-cleanup</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>webwork</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
FreeMarker
If you are using FreeMarker for your SiteMesh decorators, we recommend using the FreeMarkerPageFilter. This is an extension of the SiteMesh PageFilter, which should be placed in the web.xml in between the ActionContextCleanUp and the FilterDispatcher. Now the FreeMarker decorators will have access to WebWork variables such as ${stack} and ${request}.
<filter>
<filter-name>webwork-cleanup</filter-name>
<filter-class>com.opensymphony.webwork.dispatcher.ActionContextCleanUp</filter-class>
</filter>
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.webwork.sitemesh.FreeMarkerPageFilter</filter-class>
</filter>
<filter>
<filter-name>webwork</filter-name>
<filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>webwork-cleanup</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>webwork</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The following variables are available to the decorating freemarker page :-
- ${title} - content of <title> tag in the decorated page
- ${head} - content of <head> tag in the decorated page
- ${body} - content of t<body> tag in the decorated page
- ${page.properties} - content of the page properties
With the following decorated page :-
<html>
<meta name="author" content="tm_jee" />
<head>
<title>My Title</title>
<link rel="stylesheet" type="text/css" href="mycss.css" />
<style type="text/javascript" language="javascript" src="myjavascript.js"></script>
</head>
<body<
<h1>Sample</h1>
</body>
</html>
| Properties |
Content |
| ${title} |
My Title |
| ${head} |
<link rel="stylesheet" type="text/css" href="mycss.css" />
<style type="text/javascript" language="javascript" src="myjavascript.js"></script>
|
| ${body} |
<h1>Sample</h1>
|
| ${page.properties.meta.author} |
tm_jee |
Applying Freemarker decorator in tag form
Method 1: Using WebWork's Freemarker applydecorator Transform
This is the WebWork component that implements Freemarker's ApplyDecorator
Transform. To use this Freemarker Transform, it needs to be enabled in
webwork.properties (which is enabled by default)
webwork.freemarker.sitemesh.applyDecoratorTransform = true
An example of usage would be as follows:-
In Sitemesh's decorators.xml
<decorators defaultdir="/WEB-INF/decorators">
....
<decorator name="panel" page="/panelDecorator.ftl" />
</decorators*gt;
Decorator (panelDecorator.ftl)
<table border="1">
<tr>
<td>${title}</td>
</tr>
<tr>
<td>${body}</td>
</tr>
</table>
Freemarker page that uses decorator
<html>
<head>
<title>some title</title>
</head>
<body>
<h1>some body title</h1>
<@sitemesh.applydecorator name="panel" page="/pages/pageToBeDecorated.ftl" />
</body>
</html>
An example of pageToBeDecorated.ftl
<html>
<head>
<title>Panel Title</title>
</head>
<body>
Panel Content
</body>
</html>
The nett outcome would be:-
<html>
<title>some title&l/title>
<body>
<h1>some body title</h1>
<table border="1">
<tr>
<td>Panel Title</td>
</tr>
<tr>
<td>Panel Content</td>
</tr>
</table>
</body>
</html>
The following are method hooks available to ApplyDecoratorBean and its subclass
- getFreemarkerTemplate(String templatePath) - create a Freemarker Template based on the template path given
- parsePageFromContent(String content) - returns a Sitemesh Page object based on the content as the to-be-decorated-page
- parsePageFromAbsoluteUrl(String absoluteUrl) - returns a Sitemesh Page object using the absoluteUrl to get the content of the to-be-decorated-page
- parsePageFromRelativeUrlPath(String relativeUrl) - returns a Sitemesh Page object using the relativeUrl to get the content of the to-be-decorated-page.
- getSitemeshFactory() - returns a Sitemesh Factory object
- getPageParser(String contentType) - returns a Sitemesh PageParser object
- getDecorator(HttpServletRequest request, String decoratorName) - returns a Sitemesh Decorator object with the decoratorName supplied.
- deduceLocale(ActionInvocation invocation, Configuration freemarkerConfiguration) - deduce the Locale from invocation else use the Locale supplied by Freemarker
- createModel() - create a Freemarker model for the template
Method 2: Using Sitemesh's ApplyDecorator Tag
Add Sitemesh's FreemarkerDecoratorServlet to web.xml
<servlet>
<servlet-name>freemarkerDecoratorServlet</servlet-name>
<servlet-class>com.opensymphony.module.sitemesh.freemarker.FreemarkerDecoratorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>freemarkerDecoratorServlet</servlet-name>
<url-pattern>*.dec</url-pattern>
</servlet-mapping>
Add in Sitemesh decodator in decorator.xml eg.
<decorators>
...
<decorator name="panel" page="panelDecorator.dec" />
</decorators>
Use Sitemesh's ApplyDecorator tag in page eg.
<#assign page=JspTaglibs['/WEB-INF/sitemesh-page.tld'] />
...
<@page.applyDecorator name="panel" page="/pageToBeDecorated.ftl" />
...
An example of pageToBeDecorated.ftl
<html>
<head>
<title>Some Title</title>
</head>
<body>
Some Body
</body>
</html>
An example of panel.dec
<table border="1">
<tr>
<td>${title}</td>
</tr>
<tr>
<td>${body}</td>
</tr>
</table>
Nett effect after applying decorator
<html>
...
<table border="1">
<tr>
<td>Some Title</td>
</tr>
<tr>
<td>Some Body</td>
</tr>
</table>
...
</html>