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.
A valve is designed with a very generic interface
org.apache.catalina.Valve. Tomcat also provides an abstract class
org.apache.catalina.valves.ValveBase that 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.
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.