Here is something that made me want to slam someone’s head through a wall today.
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:
docBase
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
…
autoDeploy
set to “true” and a running Tomcat allows for:
- Deployment of .WAR files copied into the Host
appBase
.
-
Deployment of exploded web applications which are
copied into the Host appBase
.
-
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 unpackWARs
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
$CATALINA_HOME/conf/[enginename]/[hostname]/
directory.
-
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]
And:
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.