In this article, I will show you how to use SiteMesh in your JEE web sites in order to bring a sense of unity to them.
When talking about templating, the method everyone uses at first is to use
<@include>tags throughout the JSP pages. This course of action is flawed from the start since all JSPs are responsible to call includes and thus, there’s no real enforcement to use the correct ones.
The most used method is Apache Tiles. To be frank, I didn’t have a look at Tiles since it went from Struts to Apache. Struts Tiles were meant to be used in conjunction with Struts. Apache Tiles seems to support many more technologies (JSP, Velocity, Freemarker, …) but I didn’t see any JSF support out-of-the-box though there seem to exist plenty of articles that tackle the subject and its problems.
When I used Struts Tiles, I found it was a very powerful framework, yet many junior developers had some problems with it. In most projects I worked on, a senior developer assembled tiles while junior ones created the pages themselves. I found Tiles very configurable but this came at the cost of complexity. In most cases, I didn’t need all the functionalities of Tiles: I only wanted to have a header, a footer and a menu nicely crafted around my main page.
When investigating AppFuse, I stumbled upon a nice templating tool that just does that: SiteMesh. SiteMesh is technology-neutral, meaning it can be used with whatever view framework is used, JSF included. It is based on the very simple concept of servlet filters. An XML file forms the basis of the template’s configuration. This configuration holds what pages are decorated and with what templates.
The templating mechanism is made so each page is seen as complete either when viewed standalone or when viewed through the filter. For example, when you write the page normally, you provide the title’s text (what is displayed in most browser’s title bar). If you are using SiteMesh, nothing changes. At runtime, the servlet filter reads the title’s text value from the source HTML (which can come from a dynamic source) and outputs the decorated page with the same title’s text value, although the page design will be different.
The following example shows how it is achieved in the template:
<html> <head>...</head> <body> <div id="top">Header</div> <h1><decorator:getProperty property="title" /></h1> ... </body> <html>
Nothing could be simpler. Yet, the solution decouples the standalone view from the decorated view. The former has no need to know about the latter!
Moreover, the choice of which decorator(s) to use can come from different strategies:
- configuration files,
- browser language,
- display agent (browser or printer),
The simplicity and the robustness of the solution is what will make me deeply think about using it if I have simple templating needs. On the opposite site, if you have complex templating requirements, SiteMesh won’t be enough.
You will find a very simple project here in Maven/Eclipse format.
To go further:
In this article, I will show you how to replace filters declared in web.xml with unobtrusive mechanism in Tomcat.
I’m a big friend of Apache Tomcat. In many cases, even enterprise applications can run with a simple JSP - servlet container and Tomcat has passed through all the evolutions of the standards with flying colors. This is not to say that other containers are bad (Jetty for instance, is very good at being embedded), only that I know enough about Tomcat to know it’s stable and bugfixes are regularly available: a condition for using a product in the enterprise. I am always amazed at why so few Tomcat run in production, compared to big fat application servers. Is it because it is too simple? Yet, it can be very powerful, as I will show with the Valve concept.
Designers and architects know about the Intercepting Filter pattern: these filters intercept requests and responses and can be chained. The implementation of this pattern is the javax.servlet.Filter interface available since Servlet v2.3. Let’s take an example: suppose you have to get additional informations in a database (suche as name, ect.) when authentifying with a classical JAAS login. Since your application is not responsible for performing the check, it is impossible to get these infos at the right time. It is very simple when using a filter.
First problem: you do not want your developers to write the database access code with each new application. You create the filter once, put it in the JAR and tell your teams to use this filter in their web.xml once and for all. Now your enterprise evolve and put information relative to people in a LDAP server (not really a bad idea). For newly created applications, you create another filter that access LDAP and use it from now on.
Second problem: what do you do with your applications that use the legacy filter?
- You can run a batch that update the web.xml throughout your entire filesystem. Well, for me, that's too risky... I wouldn't want to get my production down in one big shot! And if the webapps run in non-exploded mode, it is impossible.
- You can still use the database and create a batch that synchronize data from the LDAP server to the database. Not risky at all. And 20 years latter, your information system is a big plate of spaghetti because information is duplicated everywhere. Not very urban.
- Finally, you can rely on our Tomcat friend from the beginning, remove the filter from applications at all and put a specific filter called a valve in Tomcat itself. A big disadvantage is that you now are coupled to Tomcat. This is not as bad as it sounds since the code is so isolated it can safely be migrated to another application server API real quick.
I suppose mad dogs would go with option 1 and managers that change every 2 years would go with option 2. Of course, from my clearly subjective presentation of the solutions, you can guess i would go with option 3.
"Valve is a request processing component associated with a particular Container. A series of Valves are generally associated with each other into a Pipeline."
From Tomcat's Javadoc
A valve is designed with a very generic interface
org.apache.catalina.Valve. Tomcat also provides an abstract class
org.apache.catalina.valves.ValveBasethat can be safely extended. The main method of the latter is the
invoke()method where you can access both request and response. Don’t forget to call the next valve in it or, like in filters, the chaining will stop.
From this point, you are free to do as you choose: access the LDAP server, put a cookie, log performances, etc.
You can find the Maven sources for 2 very simple examples here.
To go further:
Please note that the links point to the latest v6.0 version but the concepts exposed above are available in v5.5 and v4.1.
Posts Tagged ‘filter’