I need to understand why using the below code to add a webapp dynamically to the embedded tomcat giving the following error, when we add Context on startup everything works fine, the code is the same. Code:
/*
* Add a context to the host and contexts map; be careful to call this only
* within a synchronization block of this.contexts
*/
private Context addContextDynamically(String contextPath, String folderName) {
logger.info("Adding context " + contextPath + " at " + folderName);
Context contextNew = this.embedded.addWebapp(this.host, contextPath, folderName);
// Context contextNew = this.embedded.addContext(this.host,contextPath,
// folderName);
// this.embedded.addContext(host, contextPath, dir)
// logger.info("contextNew-->"+contextNew);
List<File> filterdJarfiles = getAppJarFilesAlone(folderName);
WebResourceRoot resources = new StandardRoot(contextNew);
for (File jf : filterdJarfiles) {
String st = jf.getAbsolutePath().substring(0, jf.getAbsolutePath().lastIndexOf(File.separator));
logger.info("st-->"+st);
resources.addPreResources(new DirResourceSet(resources, "/WEB-INF/lib", st, "/"));
}
logger.fine("Adding context setResources " + resources);
logger.fine("Adding context contextNew "+ contextNew);
logger.fine("Adding context filterdJarfiles " + filterdJarfiles.toString());
try {
contexts.put(contextNew.getPath(), contextNew);
contextNew.setResources(resources);
INexxWebappLoader loader = new INexxWebappLoader(contextNew.getParentClassLoader(), contextNew);
contextNew.setLoader(loader);
// host.addChild(context);
cleanContextWorkDir((StandardContext) contextNew);
}catch (Exception e) {
logger.info("Caught exception while adding context :"+ e.getLocalizedMessage());
e.printStackTrace();
}
return contextNew;
}
The error we get is :
java.lang.IllegalStateException: Error starting static Resources
at org.apache.catalina.core.StandardContext.setResources(StandardContext.java:2470)
at com.medicity.iNexx.AppServer.addContextDynamically(AppServer.java:541)
at com.medicity.iNexx.AppServer.monitorEnablements(AppServer.java:439)
at com.medicity.iNexx.AppServer.run(AppServer.java:345)
at com.medicity.iNexx.AppServer.init(AppServer.java:244)
at com.medicity.iNexx.AppServer.main(AppServer.java:335)
So basically our product downloads the zip and unzip it in the web app directory and in the server.xml we have set:
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
If you add a Context
to a running Host
, it will be started automatically unless the property startChildren
is set to false
on the Host
component. You probably don't want this, since your addContextDynamically
needs to configure the context first.
Therefore in the method used to configure Tomcat you need to call:
final Host host = this.embedded.getHost()
if (host instanceof ContainerBase) {
((ContainerBase) host).setStartChildren(false);
}
and you need to add to addContextDynamically
:
final State hostState = this.embedded.getHost().getState();
if (hostState.isAvailable() || LifecycleState.STARTING_PREP.equals(hostState)) {
contextNew.start();
}
Cf. the source code for more information.
Remark: Contexts added before the Host
starts are immune to the startChildren
property.