2009-09-25

Tomcat6 fails to deploy a war file

Tomcat can get confused. Today I dealt with an issue where Tomcat just wouldn't deploy a war file on one of our webapp servers, so the app was unavailable. The first symptom of the problem was a Tomcat 404 page.
type Status report
message /mywar/default
description The requested resource (/mywar/default) is not available.
The file mywar.war was plainly in $TOMCAT_HOME/webapps/, and the Host was configued with unpackWARs="true" and autoDeploy="true" so Tomcat should recognize a new or changed war file and deploy it within just a few seconds. Flailing about, I changed the war file name to mywar2.war, and Tomcat deployed it without delay. When I changed the name back to mywar.war, the mywar2 context was undeployed, but it just ignored mywar.war, so there had to be something specific to the war file name. Next I tried stopping and starting Tomcat. This had worked in a similar situation a few weeks back.
bin/shutdown.sh && tail -f logs/catalina.out #wait until shutdown is completed
bin/startup.sh && tail -f logs/catalina.out
My first real clue was finding this in the shutdown output:
Sep 25, 2009 12:57:49 PM org.apache.catalina.startup.HostConfig.undeployApps
WARNING: Error while removing context [/mywar]
java.lang.NullPointerException
        at org.apache.catalina.core.ContainerBase.removeChild(ContainerBase.java:915)
        at org.apache.catalina.startup.HostConfig.undeployApps(HostConfig.java:1248)
        at org.apache.catalina.startup.HostConfig.stop(HostConfig.java:1219)
        <snip>
which seems to imply that Tomcat though the war was already deployed. Then on startup:
INFO: Deploying web application archive mywar.war
Sep 25, 2009 12:58:41 PM org.apache.tomcat.util.digester.Digester
fatalError
SEVERE: Parse Fatal Error at line 1 column 1: Premature end of file.
org.xml.sax.SAXParseException: Premature end of file.
        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:174)
        at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:388)
        at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1414)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:1059)
        <snip>
This clearly shows that Tomcat was attempting to deploy the webapp, but it failed to parse some XML file. When I tried touching the war file, Tomcat still ignored it; no error in the log this time. I vaguely remembered that Tomcat creates a file for (some?) webapps somewhere in $TOMCAT_HOME/conf/, so I used one of my favorite *nix tools, find.
find conf -name "*mywar*"
conf/Catalina/localhost/mywar.xml
The file simply contained:
<xml version="1.0">
<Context path="" />
I deleted the file, stopped and restarted Tomcat again, and blammo - webapp deployed. My guess is that the app hadn't been undeployed properly at some point, causing Tomcat to keep the context file around without the exploded war content.
In my subsequent research, I found that this file can be used to register a webapp with Tomcat without the need to create a war file. If I have a webapp in /home/mpartridge/workspace/MyProject/web, I can create the file $TOMCAT_HOME/conf/Catalina/localhost/MyProject.xml:
<xml version="1.0">
<Context path="/mywar"
 docBase="/home/mpartridge/workspace/MyProject/web"
 reloadable="true" />
and Tomcat will serve the webapp. Then whenever I make a change, Tomcat will automatically reload the context.

11 comments:

  1. Thank you! I faced the same problem too. Solved after removing the xml file in conf/Catalina/localhost/

    ReplyDelete
  2. Whew! I was stumped for a whole evening with this problem. Thanks for describing the solution.

    ReplyDelete
  3. Nice, you rock, thanks for the solution.

    ReplyDelete
  4. Really appreciate the post. I never remember this issue and it always seemed to cost me the better part of a day when deploying new services. Thanks to you I was up and running again in a couple minutes.

    ReplyDelete
  5. Thanks for your solution.... It helped a lot

    ReplyDelete
  6. Thanks for your solution. It realy helped me.

    ReplyDelete
  7. I just experience this problem and your article brighten up my day, Thanks!

    ReplyDelete
  8. Anyone know what's causing this to get corrupted to begin with? Would be nice to avoid it entirely. Thanks.

    ReplyDelete
  9. I haven't been able to find anything definitive on that question, Chazz. Please let me know if you do! :-)

    ReplyDelete
  10. Thanks, I had the same symptom but my problem was different. I turned out I'd had a subversion conflict I hadn't noticed and it had corrupted my web.xml file. I discovered it by trying the war in a separate tomcat7 deployment. tomcat7 has much better error logging.

    ReplyDelete
  11. Hello maybe you can help, sometimes when I deploy a .war the server is unreachable, I wait 2 or 5 minutes and try again (stop and start tomcat), the server continue unreachable, my solution is reboot the system, and this works again, I have 7 domains, I watch the log always with "java.net.BindException: Address already in use: " or similar, please help me to fix it, it's very annoying reboot the system accacionally.

    ReplyDelete