Configuration Antipatterns: Tomcat
by Robert Cooper
If you have worked with Tomcat before, you are no doubt familiar with the context.xml file. This is where you configure container managed resources. It has one property on the <context> tag that we were using explicitly. This is from the Tomcat docs as they are today:
The Document Base (also known as the Context Root) directory for this web application, or the pathname to the web application archive file (if this web application is being executed directly from the WAR file). You may specify an absolute pathname for this directory or WAR file, or a pathname that is relative to the appBase directory of the owning Host.
The appBase is the default "webapps" folder.
Now, the ways we are using it are rather beside the point, there are a number of reasons you might want to deploy the same docBase multiple times: perhaps you want to run the same webapp with different database settings, or a different authentication system. However, there is something that is left out of here. declaring [docBase="myApp"] for a context path of "app" will fail. Even worse, it fails with one of those stupid log messages:
WARNING: A docBase C:\apache-tomcat-5.5.20\webapps\myApp inside the host appBase has been specified, and will be ignored.
[Then it continues booting like this isn't a big deal..]
SEVERE: Error starting static Resources
java.lang.IllegalArgumentException: Document base C:\apache-tomcat-5.5.20\webapps\app does not exist or
is not a readable directory
Yeah, because you aren't doing what I explicitly told you to do. This is software 101 here people: if you have a configuration option, what I give you as the configuration should be what you bloody well use. If stuff goes wrong from that point on, it is my fault. Defaults save me from myself, but if I want to shoot myself in the foot, let me. Sometimes there might be an alien or something on that foot and it actually is good idea.
Honestly, I was baffled. Why would someone do this? Who in their right mind would take a user-supplied explicit configuration and clobber it irrecoverably with a default value? It took me a while to think through, but I finally understood the reasoning here: a completely lazy programmer.
Lets look at another snippet of the docs:
Deploying on a running Tomcat server
autoDeployset to "true" and a running Tomcat allows for:
- Deployment of .WAR files copied into the Host
Deployment of exploded web applications which are
copied into the Host
Re-deployment of a web application which has already been deployed from
a .WAR when the new .WAR is provided. In this case the exploded
web application is removed, and the .WAR is expanded again.
Note that the explosion will not occur if the Host is configured
so that .WARs are not exploded with a
attribute set to "false", in which case the web application
will be simply redeployed as a compressed archive.
Re-deployment of a web application if the /WEB-INF/web.xml file (or any
other resource defined as a WatchedResource) is updated.
Re-deployment of a web application if the Context Descriptor file from which
the web application has been deployed is updated.
Re-deployment of a web application if a Context Descriptor file (with a
filename corresponding to the Context path of the previously deployed
web application) is added to the
Undeployment of a web application if its document base (docBase)
is deleted. Note that on Windows, this assumes that anti-locking
features (see Context configuration) are enabled, otherwise it is not
possible to delete the resources of a running web application.
[ed: emphasis mine]
Undeploy an Existing Application
WARNING - This command will delete any web application artifacts that exist within appBase directory (typically "webapps") for this virtual host. This will delete the the application .WAR, if present, the application directory resulting either from a deploy in unpacked form or from .WAR expansion as well as the XML Context definition from $CATALINA_HOME/conf/[enginename]/[hostname]/ directory. If you simply want to take an application out of service, you should use the /stop command instead.
(Note, WARNING is red and bold here in the original)
You see, rather than confirm in the deployer that the docBase was not in use by another context before deletion, it simply short circuits this by taking away flexibility. Now, frankly, knowing the risks associated with this, I am perfectly happy to continue along setting my docBases to shared folders. However, I no longer even get the option.
There is an alien on my foot, and Tomcat is going to let it eat me.
|When I saw your headline, I thought that you might be saying that Tomcat IS a configuration antipattern -- but then you just tackled one little problem. ;)|
|Well, it is one little problem, but I honestly can't overstate what I feel about the configuration issue. I am a HUGE proponent of convention over configuration. This, however, represents a trump of configuration WITH configuration, and that is at such a fundamental level, WRONG, I can't even begin to express my frustration.|
You are not alone. the entire context configuration has become convoluted in t5 and t6. The docs need some work. It was interesting to find that they now have ant tasks to drive deployment using the manager app.
I'm using Tomcat with JBOSS, and it is even worse, because most documentation on the web talks about 'pure' Tomcat only. With JBOSS tomcat is palced under a '.sar' -directory, which is in the same directory as all reployed web-apps. Right now I just don't seem to get the docBase -feature to work at all, there are too many options, and no error-message giving a clue which of them might be wrong. It is truly frustrating, spending so much time on this, and finally giving it up. Thanks - Galaxy
|Yes that is lame. The question remaining is how to get that damn WARNING, which clearly should be a SEVERE, to go away and get my app actually served via the tomcat god again. Help?!|
|Two years later, Tomcat 6 still gave me the same error when I tried to deploy two instances of Solr on it.|
chill the feck out mate.