Matt Raible has a post here discussing how to use Sitemesh to decorate multiple webapps. When applying this to various Struts 2 webapps that use Freemarker, I found the process required a little further fine tuning. I’ve outlined the steps I’ve taken to get this working here.
One key issue to keep in mind is that the struts 2 sitemesh filter that comes with Struts 2 cannot refer to decorators in other webapps. This isn’t documented anywhere and certainly tripped me up.
- Configure a web app to host the decorators. This should have a web.xml that includes something like the following:
<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>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>sitemesh-freemarker</servlet-name>
<servlet-class>com.opensymphony.module.sitemesh.freemarker.FreemarkerDecoratorServlet</servlet-class>
<init-param>
<param-name>TemplatePath</param-name>
<param-value>/</param-value>
</init-param>
<init-param>
<param-name>default_encoding</param-name>
<param-value>ISO-8859-1</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>sitemesh-freemarker</servlet-name>
<url-pattern>*.ftl</url-pattern>
</servlet-mapping>…
Note that this webapp is thus set up basically just to use Freemarker and Sitemesh together as outlined here.
- Struts 2 web apps that will use the shared decorators in some other webapp must NOT use the struts2-sitemesh PageFilter that comes with Struts 2, but instead use the PageFilter that comes with the regular sitemesh distribution:
- Struts 2 web apps point to decorators in the host webapp, as outlined in MR’s post:
<decorators>
<excludes>
<pattern>/styles/*</pattern>
<pattern>/scripts/*</pattern>
<pattern>/images/*</pattern>
<pattern>/index.html</pattern>
<pattern>/admBase/*</pattern>
<pattern>/jforum.page?module=admBase*</pattern>
</excludes>
<!– load decorator from a different web-app deployed in the server –>
<decorator name=“layout” webapp=“yourWebApp” page=“/WEB-INF/decorators/YourDecorator.ftl”>
<pattern>/*</pattern>
</decorator></decorators>
- crossContext must be set to true for all your webapps. (Your context elements will no doubt look considerably different, especially if you’re loading webapps from server.xml rather than individual context files)
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
</filter>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<Loader delegate=“true”/>
</Context>
And you should be good to go.