The “Tomcat” Anti-Pattern
While it is part of a larger set of anti-patterns, which one might refer to as the ‘it will do for now’ anti-pattern set, the “Tomcat” anti-pattern is particularly prevalent in my experience, and easier to describe than the full set.
The pattern essentially consists of utilizing Apache Tomcat as a Java server, while pulling in most or all of the libraries that constitute a more modern Java server, such as Glassfish, JBoss Wildfly etc. The process by which this occurs is roughly along the following lines:
Ø At the beginning of the project, Tomcat is chosen by default, if reasons are given, they usually comprise ‘it’s simple’, ‘we don’t need more’, and a usually unstated reason — “we don’t have to mess with OSGi”.
Ø For better performance libraries such as Grizzly HTTP, Jersey, Jackson etc. are added to the project, which if the project uses Maven is extremely easy to do without raising questions.
Ø Eventually most if not all of the libraries that comprise Glassfish or another Java server are part of the project, but running in the less-than-ideal Tomcat container, rather than a more robust, faster OSGi container such as Felix.
This begs the question, of course, why not use Glassfish or Wildfly (or any other modern Java server) in the first place? The Tomcat container has more race conditions than the Paris-Dakar rally, and libs like Grizzly and Jersey are tested primarily as part of Glassfish, running in the Felix OSGI container. Deploying to Glassfish is more dynamic and if anything easier than to Tomcat in any current IDE, and there are innumerable ways of bundling your code as OSGi bundles, from Maven plugins to the dozen or so ways of doing so in Eclipse. WAR files automatically deploy to Glassfish, and the servlets are bundled. None of this is rocket science.
Yet in more projects than I’ve seen simply use Glassfish or JBoss etc., the antipattern of dumping libraries largely untested in Tomcat into the already unstable Tomcat container is the common modus operandi. This remains the case despite Glassfish being the reference implementation for Java EE (from which many of the technologies used arose) and works extremely well with Spring, the major alternative to Java EE, and one that utilizes many of the same libraries.
The problem appears to be that while using OSGi based servers is largely transparent to the developer of a Spring or Java EE application, there’s a fear that it won’t be, largely being propagated by those who have never bothered to actually try it.
Undoing all the extra work created by using Tomcat, though, in order to remove it once a project is in production, becomes a remarkably time-consuming refactoring job.
Of course, there are worse things. I saw an instance of this anti-pattern on steroids, where not only were many libraries brought in to destabilize Tomcat further, 18 instances of Tomcat were then running simultaneously in one JBoss instance. The result? Rather than an average startup time of under 20s for a full Glassfish instance, the server took ~35 minutes to startup, and hot-deploy wasn’t in the vocabulary.