Thursday, August 9, 2007

Auto-deploying to Tomcat from CruiseControl with Maven

We have a web project that gets built using Maven; it was relatively simple to get this running under CruiseControl since CC has pretty good Maven2 support. However, we also wanted to have a successful build actually deployed to a Tomcat somewhere at a known location so that people could always check out the latest version.

I played around with various maven plugins for working with Tomcat, but had a really hard time getting them to work properly. Then I realized, even if I got the maven plugins working, I would need to do something else, because we run into PermGen errors on our Tomcats when we undeploy/redeploy, so we'd actually need to do an undeploy/restart-tomcat/deploy loop instead. Of course, none of the tomcat plugins can do the restart-tomcat bit (they can shut it down, but because they interact with the tomcat management interface, they can't actually start it up again!).

So, I went back down the script route. I wrote this script which can do the undeploy/restart/redeploy loop:

#!/bin/sh

unset DISPLAY

export CATALINA_HOME=/usr/local/lib/apache-tomcat-5.5.17
export JAVA_HOME=/usr/java/jdk1.5.0_09

TOMCAT_ADMIN_USER=admin
TOMCAT_ADMIN_PWD=XXXXXXXX
TOMCAT_PORT=13080
CC_HOME=/usr/local/lib/cruisecontrol-bin-2.6.2
CC_BUILD=$CC_HOME/checkout/trunk

# undeploy old WAR, if any
( echo "--silent"
  echo "--user $TOMCAT_ADMIN_USER:$TOMCAT_ADMIN_PWD"
  echo "--url http://localhost:$TOMCAT_PORT/manager/html/undeploy?path=/" ) | \
curl --config - > /dev/null

# stop the tomcat
(cd $CATALINA_HOME; bin/shutdown.sh)

# pause to wait for shutdown
sleep 5

# restart the tomcat
(cd $CATALINA_HOME; bin/startup.sh)

# drop the WAR in place
cp $CC_BUILD/webapp/target/ROOT.war $CATALINA_HOME/webapps

This assumes that you have the tomcat installed in the given CATALINA_HOME with the manager app enabled and set up with the appropriate admin credentials, and that the build directory for the CC project is in the "trunk/webapp" directory. Note also that we're deploying to the root context, so you will want to modify your undeploy URL if that's different.

The last step is to add the following CC project; assuming we have an existing "webapp" CC project in existence:

  <project name="webapp-tomcat" buildafterfailed="false">
    <modificationset>
      <buildstatus logdir="logs/webapp"/>
    </modificationset>
    <schedule interval="60">
      <exec command="/home/cruise/bin/redeploy"
            timeout="60"/>
    </schedule>
  </project>

This triggers off a successful CC build of "webapp" and just calls the script we wrote above. Nice and easy.

1 comments:

Andy said...

From the more-than-one-way-to-skin-a-cat section, if you want your tomcat app to be the root context, but don't feel like naming it ROOT, you can set this in the app's context xml file:

[Context path="" docBase="/tmp/myFavorite.war" debug="0" crossContext="false"]
[/Context]

(change the [] to < >)

Just name the file myFavorite.xml and put it in the $CATALINA_HOME/conf/Catalina/localhost directory.

Just came across this tidbit.

I like the war named ROOT.war however :)