We're using embedded Tomcat 7 to host a web application.
It works very well, with one slight exception.
The reason that we're using embedded Tomcat is because we need to operate on multiple platforms and our architect has made the call.
The Problem
We would like to give our users the ability to check for WAR updates while the wrapper/container Java application is running (live update). Currently they have to restart our application which is much less desirable.
Basically, our code just checks a remote server for newer WAR files, if they exist they are downloaded. The problem is that we can't seem to get the Tomcat server to shutdown or release lock that it has on the exploded WAR folders.
If we completely destroy the Tomcat instance, then we can deploy the WAR files and delete the exploded WAR folders, but Tomcat won't explode and host them until we completely kill the wrapper/container JAVA application and re-launch. Once we re-launch, Tomcat explodes the WAR files and hosts the applications nicely.
What I'm Looking For
I'm hoping that there is a way to either un-deploy the application being updated or properly shutdown/stop the Tomcat server.
Code Sample
I simplified the below code sample by not including the implementation for the downloading as this works fine.
The Tomcat instance isn't public, but just made it so for ease of use. Also, the sleep within the Thread was just thown-in to simplify the example.
The endless-loop was just put in for this sample.
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.startup.Tomcat;
...
public class Testing123
{
public static void main(String[] args)
{
final Testing123 test = new Testing123();
test.createTomcat();
test.downloadUpdate();
(new Thread())
{
public void run()
{
Thread.sleep(10000);
test.downloadUpdate();
}
}.start();
while (true)
{
// this loop is just for this example...
}
}
public Tomcat tomcat = null;
private String webappsPath = "c:\\tomcat\\webapps";
private void createTomcat()
{
this.tomcat = new Tomcat();
this.tomcat.setBaseDir(this.webappsPath);
this.tomcat.setPort("5959");
this.tomcat.getServer().setPort("5960");
this.tomcat.getServer().setShutdown("SHUTDOWN");
this.tomcat.getHost().setCreateDirs(true);
this.tomcat.getHost().setDeployIgnore(null);
this.tomcat.getHost().setDeployOnStartup(true);
this.tomcat.getHost().setAutoDeploy(true);
this.tomcat.getHost().setAppBase(this.webappsPath);
Context ctx = this.tomcat.addWebapp(null, "/app1", "APP1");
ctx.setLoader(new WebappLoader(Testing123.class.getClassLoader()));
ctx.setReloadable(true);
}
private boolean isTomcatRunning()
{
if ((this.tomcat == null) || (LifecycleState.STARTED == this.tomcat.getServer().getState()))
{
return true;
}
return false;
}
private void shutdownTomcat() throws Exception
{
if (this.isTomcatRunning())
{
if ((this.tomcat!= null) && (this.tomcat.getServer() != null))
{
this.tomcat.stop();
while ((LifecycleState.STOPPING == this.tomcat.getServer().getState()) || (LifecycleState.STOPPING_PREP == this.tomcat.getServer().getState()))
{
// wait for the server to stop.
}
}
}
}
private void startTomcat() throws Exception
{
if (this.isTomcatRunning())
{
if ((this.tomcat!= null) && (this.tomcat.getServer() != null))
{
try
{
this.tomcat.init();
while (LifecycleState.INITIALIZING == this.tomcat.getServer().getState())
{
// wait for the server to initialize.
}
}
catch (Throwable e)
{
// ignore
}
this.tomcat.start();
while ((LifecycleState.STARTING == this.tomcat.getServer().getState()) || (LifecycleState.STARTING_PREP == this.tomcat.getServer().getState()))
{
// wait for the server to start.
}
}
}
}
private void downloadUpdate()
{
this.shutdownTomcat();
// Download the WAR file and delete the exploded WAR folder...
this.startTomcat();
}
}