Apache Tomcat 6 displays the following issues:
- Does not automatically deploy applications.
- Deploys an old version of an application.
- Deploys an application that was removed.
Only Tomcat's built-in auto-deployment (which works the same in vFabric tc Server) is discussed. Other methods for application deployment (e.g. the Tomcat Manager, the Tomcat Client Deployer, or tc Server application management) are not discussed.
This article describes Tomcat 6. The mechanisms are similar in Tomcat 7, but different enough that, for clarity, only Tomcat 6 is described.
However, these documents are simultaneously heavily detailed and generic to many purposes, and it can be difficult to understand the implications. Administrators may be surprised to find that their application is not deployed at all, deployed unexpectedly, or deployed with a different version than expected.
Note: For clarity, this article will assume standard/default configuration values for Engine name ("Catalina"), Host name ("localhost"), and Host appBase ("webapps"). If you are using different values, adjust these where you see them in this article. Some finer points are ignored in favor of clarifying the common case.
Tomcat's auto-deployment mechanism recognizes apps to deploy in three forms:
- A directory with web application content.
- A WAR file, which is essentially just a zipped web application directory.
- A context descriptor, which is the least-known of the three. Not to be confused with a deployment descriptor (the /WEB-INF/web.xml file in an application), a context descriptor is an XML file with a Context element specifically for Tomcat. It may be supplied by a web application itself (as /META-INF/context.xml) or by a Tomcat administrator independent of the app (as $CATALINA_BASE/conf/Catalina/localhost/[appName].xml). This can be used to define Tomcat-specific options, overriding the Context element definition in conf/context.xml.
Tomcat configuration optionsThe first step to understanding auto-deployment is to understand what the options on the Host element in conf/server.xml really do. In terms of auto-deploy, the following (from the standard Host implementation) are the main ones you need to know. For this article, we assume these are all left as the defaults unless otherwise stated.
- deployOnStartup - you should leave deployOnStartup="true" (the default) to have Tomcat deploy applications automatically when started.
- autoDeploy - you should leave autoDeploy="true" (the default) to have Tomcat check periodically after startup for new or updated applications to deploy.
- unpackWARs - when true (the default), Tomcat first un-zips ("explodes") WAR files into a directory in webapps/ (this is called the "exploded" directory), which could affect later deployments. If false, Tomcat simply deploys WAR files directly, without exploding them.
- deployXML - when true (the default), Tomcat reads the /META-INF/context.xml (if any) from the application it is deploying, uses it during the deployment, and saves it as $CATALINA_BASE/conf/Catalina/localhost/[appName].xml, unless there is already one there (in which case, that one is used instead). This can affect later deployments.
Tomcat auto-deployment in action
At startup time, with the assumptions above, Tomcat deploys applications as follows:
- Apps described by context descriptors in conf/Catalina/localhost/ are deployed. A descriptor may be present because an administrator put it there, or because a previous deployment included a META-INF/context.xml, and Tomcat copied it to the directory.
- WAR files in webapps/ are deployed, unless already deployed in step 1 or if there is a directory of the same name in webapps/. So, for example, if there is a petcare.war and a petcare/ directory under webapps/, the WAR deploy is skipped.
- Directories in webapps/ are deployed, unless already deployed in step 1.
When an application is deployed by the auto-deployer, if it is a WAR, it will be un-zipped as described by unpackWARs above. If it has a context descriptor, it is copied as described by deployXML above. These may affect auto-deployment later.
Once Tomcat is started, the auto-deployer watches for additions and updates to the following, and deploys (or re-deploys) the affected app. Updates are indicated by an updated filesystem timestamp on:
- Context descriptors in conf/Catalina/localhost/
- Top-level directories in webapps/ - on update, any context descriptor is also removed and re-deployed.
Note: the timestamps are checked only on the directories themselves, not directory contents.
- WAR files in webapps/ - on update, any context descriptor and un-zipped directory are also removed and re-deployed
- The application's deployment descriptor (WEB-INF/web.xml file in the exploded directory)
Re-deploying means briefly un-deploying the application and then deploying the new version. This typically results in a few seconds where the application is unavailable for incoming requests.
The auto-deployer also acts on deleted apps in webapps/ and deleted context descriptors in conf/Catalina/localhost/ by un-deploying the related application.
Understanding common issues
Applications are not deployed or not re-deployed
If a previous administrator has changed the defaults and disabled auto-deployment for a Tomcat instance, a new administrator may be surprised by applications not being automatically deployed.
If the Host element in conf/server.xml sets deployOnStartup="false", then nothing is deployed at startup. In this case, administration is probably intended to be performed by a separate tool.
If the Host element in conf/server.xml has autoDeploy="false", the auto-deployer is disabled and Tomcat does not check for updates to applications after startup. Administrators may do this for performance reasons or for more explicit control over updates. With this setting, the administrator must either use another method to deploy updates explicitly or restart Tomcat to deploy updates.
If these settings are at the defaults ("true" in both cases) but automatic deployment is not occurring, then deployment is probably failing due to errors. Look in the error logs for ERROR or SEVERE messages.
The previous version of an application remains deployed
This may occur in at least two situations.
- Symlinked application. If a WAR or directory in webapps/ is actually a symbolic link, Tomcat's auto-deployer does not track and re-deploy application changes (see the Context docBase documentation). Re-deploying a changed symlink requires either restarting Tomcat or manually un-deploying and re-deploying (delete and replace the symlink).
- Cold deploy. An administrator may attempt to update an existing application by shutting down Tomcat, placing the updated WAR file in webapps/, and then starting Tomcat. This is referred to as a "cold deploy" (as the change occurs while the server is not running).
Under the defaults, this strategy typically does not work as desired. With unpackWARs="true", the auto-deployer exploded the previous version of the app into a directory. When Tomcat is restarted with an updated WAR, according to the deployment sequence, the WAR file is ignored, and either a context descriptor or the directory is deployed. Therefore the previous version of the app is deployed, not the updated version in the WAR.
In order to cold deploy correctly, in addition to updating the WAR file, remove the exploded directory from webapps/ and any context descriptor from the app in conf/Catalina/localhost/. Then the auto-deployer uses the updated WAR file for deployment at startup.
Application deployed after being un-deployed
This may happen in several ways:
- Tomcat un-deploys an application when its WAR file, exploded directory, or context descriptor is removed. However, depending on the method, Tomcat does not always remove the WAR and exploded directory (see what is deleted according to the Automatic Application Deployment documentation). If a WAR or directory remains in webapps/, Tomcat's auto-deployer deploys it at next startup. To ensure this does not occur, make sure any WAR, exploded directory, and context descriptor are removed before the next Tomcat restart.
As an example, if an application is deployed as a WAR, then un-deployed by removing the exploded directory or context descriptor, the WAR file remains to be auto-deployed at the next restart. Remove the WAR instead to have all artifacts properly deleted.
- Under some operating systems (Windows being the most common), un-deploying may not succeed in removing all files. If the WAR file is removed, the application is un-deployed but the Tomcat auto-deployer cannot remove all exploded directory contents because they are locked by the JVM and OS. Because the directory remains, the auto-deployer attempts to deploy it at next startup, resulting in a partial (generally very broken) deploy. This can also block successful hot re-deployment of an application.
This problem can be resolved by setting one of the antiJARLocking or antiResourceLocking Context attributes to "true". Both options slow down deployment. With antiJARLocking, the other caveat is that it doesn't address non-JAR resources that are locked (so deletion may still fail depending on the app). With antiResourceLocking, deletion succeeds, but there are caveats regarding JSP reloading and webapps outside the webapps/ directory. Depending on your situation, you may decide it is easier to do without hot un-deploy/re-deploy on Windows.
When a Context element is defined for a Host in server.xml (which is strongly discouraged), this context is deployed at startup in addition to anything deployed by the auto-deployer. This deployment cannot be removed or re-deployed while the server is running. If the same application is deployed both from the server.xml and the auto-deployer, this is what the Automatic Application Deployment docs section is referring to when it warns about being "deployed twice." This can lead to at least two issues:
- If both methods deploy to the same URL path, then even after the auto-deployed application is un-deployed (e.g. by removing the WAR) or re-deployed, the path remains deployed with the application deployed by server.xml.
- If both methods use the same exploded webapps/ directory (even with a different URL path), then un-deploying the auto-deployed application removes this directory, and with it the resources used by the application deployed by server.xml.
- There is a method to deploy updates of an application in parallel in order to avoid interruptions in service caused by re-deploying.
- Context descriptors are not copied out of META-INF/context.xml by default.