Saturday, 7 March 2009

Composite Views with JSP

Tiles

Tiles has long been my first consideration for assembling pages from components. I got started with Tiles while working on Struts 1.x projects and went Tiles crazy before settling down to a fairly standard header, menu, content, footer approach. Apart from separating component layout from content, the nice part about Tiles and Struts integration was being able to forward to a Tiles definition without having to have a real page that assembled the components.

Tiles is Apache Tiles 2.0 these days, divorced from the Struts 1.x distribution. There are some minor syntactical differences between Struts 1.x Tiles and Tiles 2.0. <tiles:put> becomes <tiles:putAttribute>, for example, but this is just a minor irritation.

I've used Tiles 2.0 very successfully with both Spring MVC and Struts 2 applications. Integration is very straightforward in both cases and you quickly forget that you are using Tiles.

In both cases you define the TilesListener (or the TilesServlet or the TilesFilter) in your web application deployment descriptor:

web.xml
<listener>
    <description>Tiles Listener</description>
    <listener-class>org.apache.tiles.web.startup.TilesListener</listener-class>
</listener>

With Spring MVC, you define a view resolver for Tiles and you can then use a Tiles definition in the view name that you return from your ModelAndView.

dispatcher-servlet.xml
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>

With Struts 2, you define a new result type, optionally making it the default result type with the default="true" attribute. You can then use the Tiles definition in an action result.

struts.xml
<result-types>
    <result-type name="tiles" default="true" class="org.apache.struts2.views.tiles.TilesResult"/>
    ...
</result-types>

I've also tried Tiles 2.0 with JSF 1.1 but it didn't really play very nicely. It wasn't possible to specify a Tiles definition in a navigation rule and there was constant fiddling with <f:verbatim> tags in the tiles themselves to prevent content getting out of order.

I note that MyFaces has a non-standard extension in the form of JspTilesViewHandlerImpl, which allows forwarding to Tiles definitions:

wiki.apache.org/myfaces/Tiles_and_JSF

Sitemesh

Sitemesh looks pretty good for page decoration stuff like headers, footers, sidebars, etc. I like the way you can inject meta-data from the page header into the decorated page. I've not got round to delving much deeper than that.

This is a nice introductory tutorial for Sitemesh:

today.java.net/pub/a/today/2004/03/11/sitemesh.html

I was aware of issues with Sitemesh and JSF so my current JSF/JPA project wasn't the time to try and explore it in more detail:

forums.opensymphony.com/thread.jspa?threadID=36939&messageID=72427 mail-archive.com/users@myfaces.apache.org/msg34480.html

Prelude and Coda

For my current project, all I needed was a basic header with a CSS stylesheet reference and a standard footer. So I used the standard, but perhaps underused, mechanism provided for in the JSP 2.0 specification:

web.xml
<jsp-config>
   <jsp-property-group>
       <display-name>All Pages</display-name>
       <url-pattern>*.jsp</url-pattern>
       <include-prelude>/WEB-INF/jspf/head.jspf</include-prelude>
       <include-coda>/WEB-INF/jspf/foot.jspf</include-coda>
   </jsp-property-group>
</jsp-config>

I like this method for a simple layout or a prototype. Minimal setup. No additional libraries, servlets, filters or tag libraries to consider. But very quickly you can make your pages look consistent and respectable.

The prelude and coda have to follow the same rules as other included fragments, in particular that JSP and tag library start and end tags must always appear in the same document. This means, for example, that I couldn't open my <f:view> tag in the header and close it in the footer. It's OK to deal with HTML tags like <html> and <body> this way of course - there wouldn't be much point otherwise.

Bear in mind also that the include of the prelude and coda content is done when the JSP is first compiled, so a clean and build may be required after you add these directives to web.xml.

No comments:

Followers