ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Advanced SiteMesh
Pages: 1, 2, 3

PageDecoratorMapper

A page can override which decorator should be used by specifying the decorator name through the META attribute.



In order to use this mapper, you have to change sitemesh.xml:

<mapper 
class="com.opensymphony.module.sitemesh.mapper.PageDecoratorMapper">
  <param name="property.1" value="meta.decorator" />
</mapper>

PageDecoratorMapper takes a list of parameters. In our example, we are instructing it that the value of decorator's META property should be used as the decorator name. So if I want to use a decorator named test for the page, all I have to do is add the following line in the header:

<META name="decorator" content="test">

PageDecoratorMapper provides a static approach for a page to choose which decorator should be used. A page can decide which decorator to use at runtime by using ParameterDecoratorMapper.

ParameterDecoratorMapper

To use a ParameterDecoratorMapper, add an entry for it in sitemesh.xml:

<mapper 
class= "com.opensymphony.module.sitemesh.mapper.ParameterDecoratorMapper">
  <param name="decorator.parameter" value="decorator" />
  <param name="parameter.name" value="confirm" />
  <param name="parameter.value" value="true" />
</mapper>

This takes three parameters:

  • decorator.parameter
    The name of the request parameter used for specifying the name of the decorator.

  • parameter.name
    The name of the request parameter used for confirming the decorator parameter.

  • parameter.value
    The value of the request parameter used for confirming the decorator parameter.

If you want help.jsp to use the test decorator, then you can invoke it like this:

help.jsp?decorator=test&confirm=true

SiteMesh provides a few more mappers that are very helpful. Some of these are:

  • FrameSetDecoratorMapper
    Should be used when page is a frame.

  • CookieDecoratorMapper
    Lets you use a cookie value for specifying the name of the decorator to be used.

  • RobotDecoratorMapper
    Will use the specified decorator when the requester is identified as a robot. You may want to add a keywords header if the page is accessed by a robot, and a decorator is a good way to do that.

Velocity and Freemarker Decorators

SiteMesh does not restrict you to use JSP while creating decorators. You are free to use either Velocity or Freemarker. Velocity and Freemarker are templating languages that can be used for creating web pages. These languages are much easier to use than normal JSP, but are not as programmable as JSP.

SiteMesh adds supports for these two templating languages through two servlets, which are part of SiteMesh.jar. We have to declare these two servlets in web.xml, as follows:

<servlet>
  <servlet-name>sitemesh-velocity</servlet-name>
  <servlet-class> 
    com.opensymphony.module.sitemesh.velocity.VelocityDecoratorServlet
  </servlet-class>
</servlet>
<!--Declare servlet for handling freemarker requests -->
<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>
</servlet>
<!-- Velocity servlet should serve all requests with .vm extension-->
<servlet-mapping>
  <servlet-name>sitemesh-velocity</servlet-name>
  <url-pattern>*.vm</url-pattern>
</servlet-mapping>
<!-- FreeMarker servlet should serve all requests with .dec extension-->
<servlet-mapping>
  <servlet-name>sitemesh-freemarker</servlet-name>
  <url-pattern>*.dec</url-pattern>
</servlet-mapping>

We also have to copy freemarker.jar, velocity-dep.jar, and velocity-tools-view.jar into the lib folder. These .jars are shipped with the SiteMesh distribution. We will change our first sample for using Velocity and Freemarker decorators instead of JSP. In our first sample we have two decorators: headerfooter and sidemenu. We will create headerfooter.dec like this:

<html>
  <head>
    <title>My Site - $Advanced SiteMesh</title>
      ${head}
  </head>
  <body>
    <table border="1">
      <tr>
        <td>SiteMesh Corporation</td>
      </tr>
      <tr>
        <td>${body}</td>
      </tr>
      <tr>
        <td>SiteMesh copyright</td>
      </tr>
    </table>
  </body>
</html>

In this page, we are using Freemarker templates for header, footer, and title instead of custom tags, but the page layout is the same. When the container receives a request for a page with a .dec extension, it will pass it to FreemarkerDecoratorServlet, which invokes FreemarkerDecorator for generating the final HTML page. We are using the $Advanced SiteMesh template for accessing the title of the web page generated by the application, ${head} for accessing the head, and ${body} for accessing the body. Freemarker provides more such templates. You can find out more about it in the Resources section below.

We also need to create sidemenu.vm in the decorators folder. This is the Velocity decoration file.

<html>
  <head>
    <title>My Site - $title</title>
      $head
  </head>
  <body>
    <table border="1">
      <tr>
        <td> SiteMesh Header </td>
      </tr>
      <tr>
        <td> Sidemenu </td>
        <td> $body </td>
      </tr>
      <tr>
        <td> SiteMesh Footer </td>
      </tr>
    </table>
  </body>
</html>

For a Velocity decorator, we need to replace decorator:title with a $title template. Similarly, we will use head and body Velocity templates instead of custom tags.

Conclusion

SiteMesh is a very flexible and easy-to-use decoration framework based on filters. But it has a couple of problems. First, filters were introduced in the Servlet 2.3 specification, so older application servers may not support them. Please check that your application is going to be deployed on a container that supports filters.

Also, a filter gets control only if a user requests that page. If you call home.jsp through a browser, it will be decorated, but if one of your servlets gives control to home.jsp through either RequestDispatcher.include() or forward(), it won't get decorated. But don't worry--in the Servlet 2.4 specification and up, you can just configure filters to be invoked in forwarding and include cases, as well as for regular requests.

Resources

Sunil Patil has worked on J2EE technologies for more than five years. His areas of interest include object relational mapping tools, UI frameworks, and portals.


Return to ONJava.com.