Why SiteMesh instead of Tiles?
The URL for SiteMesh http://www.opensymphony.com/sitemesh/. At least read the first part there under "What is it?" I think you will quickly see the benefits after going through this brief example. In summary, the main reason I like SiteMesh more than Tiles is that SiteMesh is much easier to configure and use (less typing and easier to understand). Using Tiles, you need to have your forwards go to a "tiles page" versus the direct JSP. SiteMesh takes the approach that your page (your JSP) doesn't even know or care that it's being decorated. Using Tiles, each individual page you want to go to has to be associated with a layout - Major pain! Every time you create a new JSP that you want to forward to, you have to create another tiles definition and associate it with a layout and forward to the Tile page (versus the JSP). Using SiteMesh, you basically code your Struts application by forwarding to JSPs just like you would if you were not using Tiles. With SiteMesh you can simply set up a URL pattern and all your pages are decorated with the layout you choose. Obviously, you can set up different URL patterns and you can have decorators invoked based on many other possibilities other than a URL mapping (this example shows just one other type - a request parameter).

NOTE (Added 1/5/2005): Actually, there is one thing I found using SiteMesh that you might want to consider before you use it. It actually had to be taken out of an application I was using because of this issue: Sitemesh has to store the entire content of your html body into memory before it decorates it. If you have some very large pages, such as might happen in a reporting app where you don't have paging and end up with one large page of rows, you could end up with severe memory problems since all of that content is stored in a StringBuffer before being decorated. On my local machine with not a lot of RAM given to Tomcat, it actually would bring Tomcat down. Just something to consider before you adopt SiteMesh. Tiles does not have this problem.

Using Sitemesh
I really haven't really provided much of a tutorial here. Best bet is to just download the rr-sitemesh source and look it over. Then when you finish with that, look at the examples from Sitemesh which show more usages than this simple exmaple.

I'll go through a few files below.
web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">

    <display-name>Sitemesh Example</display-name>
    <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>

    <servlet>
        <servlet-name>action</servlet-name>
        <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
        <init-param>
            <param-name>config</param-name>
            <param-value>/WEB-INF/struts-config.xml</param-value>
        </init-param>
        <init-param>
            <param-name>debug</param-name>
            <param-value>2</param-value>
        </init-param>
        <init-param>
            <param-name>detail</param-name>
            <param-value>2</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>action</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>
Only thing to note here is how we are telling the sitemesh filter to be called for all pages since we are using the url-pattern /*
decorator.xml
Place this file in the WEB-INF dir.

    <decorators defaultdir="/decorators">
        <decorator name="main" page="mainDecorator.jsp">
            <pattern>*</pattern>
        </decorator>
        <decorator name="panel" page="panelDecorator.jsp"/>
        <decorator name="popup" page="popupDecorator.jsp"/>
    </decorators>
The default dir tells us where we will place our decorator files. All requests will be decorated with "main" (mainDecorator.jsp) if no other decorator takes precedence since we are defining the pattern "*"
Create Decorators
These are analogous to Struts Tile layouts. Places the decorator jsps in your app/decorators directory. In the files below, where you see tags like: <decorator:head /> this means SiteMesh will pull the information contained between your page's head tags and insert it into the decorator at this location. The main thing it inserts is the content of your body ( <decorator:body /> ) (You can also configure other things besides the defaults based on meta tags. See the docs.)

Here are the three decorators for this example:

mainDecorator.jsp

<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>
<%@ taglib uri="http://www.opensymphony.com/sitemesh/page" prefix="page" %>
<%@ taglib prefix="bean" uri="http://jakarta.apache.org/struts/tags-bean" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title><decorator:title default="{ Unknown Page - shouldn't see this, since
    pages should define title }" /></title>
    <link href="<%= request.getContextPath() %>/decorators/main.css"
    <%--pulls the header from the page we are decorating and inserts it here --%>
    <decorator:head />
</head>

<body>
<table width="100%" height="100%">
    <tr>
        <td id="header" colspan="2">
           <bean:message key="label.header" />
        </td>
    </tr>
    <tr>
        <td valign="top" width="200">
            <%-- grabs the navigation.jsp page and decorates with the
            panel decorator and puts it here --%>
            <page:applyDecorator page="/WEB-INF/jsps/navigation.jsp" name="panel" />
        </td>
        <td>
        <table width="100%" height="100%">
            <tr>
                <td id="pageTitle">
                    <span class="pageTitle">
                        <%--pulls the title from the page we are
                        decorating and inserts it here --%>
                        <decorator:title />
                    </span>
                </td>
            </tr>
            <tr>
                <td valign="top" height="100%">
                    <%--pulls the body from the page we are
                    decorating and inserts it here --%>
                    <decorator:body />
                </td>
            </tr>
        </table>
        </td>
    </tr>
    <tr>
        <td id="footer" colspan="2">
            <bean:message key="label.footer" />
        </td>
    </tr>
</table>
</body>
</html>

Panel Decorator


    <%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator"
    prefix="decorator"
    <decorator:head />
    <div class="panelDiv">
        <span class="panelTitle"><decorator:title
        default="Unknown panel" /></span>
        <br/>
        <%--inserts the body of whatever we are decorating here --%>
        <decorator:body />
    </div>

popupDecorator.jsp


<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator"
prefix="decorator"
<html>
<head>
<title>
    <decorator:title default="{ Unknown Page -
    shouldn't see this, since pages should define title }" />
    </title>
<link href="<%= request.getContextPath() %>/decorators/main.css"
rel="stylesheet" type="text/css">
<%--pulls the header from the page we are decorating
and inserts it here --%>
<decorator:head />
</head>

<body>
<div class="popupDiv">
    <span class="popupTitle">
    <decorator:title
        default="Unknown Title - shouldn't see this" /></span>
    <br/>
    <%--inserts the body of whatever we are decorating here --%>
    <decorator:body />
</div>
</body>
</html>
JSPs
The JSPs in the source code you'll see are pretty basic. The only thing to really note is that in the navigation menu you'll notice:

    <c:url var="url" value="/summary.do">
        <c:param name="decorator" value="popup"/>
        <c:param name="confirm" value="true"/>
    </c:url>
    <a href="javascript:popUp( '<c:out value='${url}'/>' );">
    Summary As PopUp</a> <br/><br/>
The key is that we are passing a decorator param of "popup." If you look back to our decorators.xml you'll see: <decorator name="popup" page="popupDecorator.jsp"/>. When the the Sitemesh filter sees a paramater passed with the name "popup" it will look for a decorator to apply (in this case 'popupDecorator.jsp').
Code and Lesson - Rick Reumann