Sunday, August 12, 2007

Tiles Killed Convention - Facelets Templating

I recently went to a developers conference and listened to a rapid application development with JSF session by David Geary. I found the session very helpful and informative but something keeps bothering me every time somebody talks about templating as he did with Facelets.

Every time I hear about templating I think it should be easier and more reuseable. I started out developing Struts applications which use Tiles. I then moved on to JSF and Tiles. The nice thing about Tiles is "it works". Sometimes just working is not enough and a little convention goes a long ways.

Recently I've been thinking about the convention over configuration mentality that RoR uses. Also I've come upon a great templating package called Sitemesh. What I love about Sitemesh is you can define a decorator and decorate multiple pages by a matching URL pattern. This is a GREAT idea. Using Tiles I've always had to create a definition for every page in a Tiles definition file, a JSP that inserts the definition, and the page that actually has the content. Well that's three files for each page of content the user sees. Now the problem I have with this is the Tiles definition for the page and the tiles insert JSP is basically repeated for every page. Sure you can define a base Tiles definition and extend it but it tends to be mostly repetitive. You can also define your tiles definition in the JSP page which is just as messy and repetitive.

Let me get back to Facelets. Facelets is a wonderful idea to use the html view and bind to components. The problem is when you get to the templating part it goes back to the Tiles mentality again. You have a page which defines a composition and a page which contains the content. The page with the composition is repeated for every content page and in most cases the exact same composition definition. This is where the convention of Sitemesh is nice and could come in handy. It would be nice if you could define a Facelets composition for a URL path and apply it to all pages in a directory. That's a heck of a start for reuse and convention over configuration. Then you can just configure the exceptions to the case which should be rare.
Sidenote: You can use JSF components in a Sitemesh decorator (http://jira.opensymphony.com/browse/SIM-201).
There are a couple of positive benefits to applying templates based on a URL path that are a side effect. I've been on too many projects where everything is thrown into the base directory of a web application or relatively few directories. This gets out of hand quickly and not good structure. There are also security packages like Acegi that will apply security based on the URL path. So if you have your files in an appropriate file structure it should be easy to find pages, apply templates, and apply security.

(If you don't think it can be done check this out: http://jira.opensymphony.com/browse/SIM-223)

This brings up another annoyance of JSF. JSF has no notion of subdirectories built in. With Struts you could define config files for each URL path and then you didn't need to put the subdirectory paths for the JSP pages in a configuration file. JSF should add this in and promote appropriate directory structure.

As a closing note if you're doing something multiple times and not much changes maybe you should refactor it out. If you are doing this in programming maybe you would extract the commonalities out into a method passing in the parameters and then the method can be reused. In the case of a templating package you should refactor the configuration out of the JSP page or Faclets xhtml view and move it into the URL path with a configuring Servlet or Filter.

No comments: