You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Tim Ramey <TR...@proclarity.com> on 2005/01/13 19:04:23 UTC

In Tomcat 5.x embedded, can't get dynamically created contexts to load

I have been trying to get Tomcat embedded in my application.  The
problem I 
am seeing is that when I attach a root context to the host, it doesn't
start 
because of a null class loader.  I have been using an example that I
found 
on the web to start embedded Tomcat; my code is below.  I have tried
this 
with Tomcat 5.0.28, 5.5.4 (other problems there), and 5.5.6.  5.0.28 and

5.5.6 exhibit the same behavior.

I stepped through the Catalina source code from 5.5.6, and this is what
I 
found:

When the root context is started (the start method of StandardContext is

called), the call to getLoader() returns null.  This seems reasonable.
An 
instance of WebappLoader is created and attached to the StandardContext 
object by calling setLoader.

Line 3917 of org/apache/catalina/core/StandardContext.java
        if (getLoader() == null) {
            ClassLoader parent = null;
            if (getPrivileged()) {
                if (log.isDebugEnabled())
                    log.debug("Configuring privileged default Loader");
                parent = this.getClass().getClassLoader();
            } else {
                if (log.isDebugEnabled())
                    log.debug("Configuring non-privileged default
Loader");
                parent = getParentClassLoader();
            }
            WebappLoader webappLoader = new WebappLoader(parent);
            webappLoader.setDelegate(getDelegate());
            setLoader(webappLoader);


Later in the same method, bindThread is called to associate the new
class 
loader with the thread.

Line 3970 of org/apache/catalina/core/StandardContext.java
        ClassLoader oldCCL = bindThread();

The problem I am seeing is that the class loader associated with the 
WebappLoader object is not created until the start method on the 
Webapploader object is called, and that method is not called until later
in 
the start method of the StandardContext object.

Line 3981 of org/apache/catalina/core/StandardContext.java
                started = true;

                // Start our subordinate components, if any
                if ((loader != null) && (loader instanceof Lifecycle))
                    ((Lifecycle) loader).start();
                if ((logger != null) && (logger instanceof Lifecycle))
                    ((Lifecycle) logger).start();

Inside the setLoader method of StandardBase, it looks like the loader is

started if the context has been started, but the context hasn't been
started 
yet - it happens after bindThread is called as well.

What happens in the bindThread class is the class loader returned from 
WebappLoader's getClassLoader method is null, causing the context class 
loader in the current thread to be set to null, causing problems
downstream.  
The error I get is at the bottom of this message.

I can work around the problem if I change the getClassLoader method in 
WebappLoader from

    public ClassLoader getClassLoader() {

        return ((ClassLoader) classLoader);
    }

to

    public ClassLoader getClassLoader() {

        if (classLoader != null) {
            return ((ClassLoader) classLoader);
        } else {
            return ((ClassLoader)parentClassLoader);
        }
    }

Is there something I am doing wrong in embedding Tomcat in my
application or 
is there a bug here?

Here is my code to start up the Embedded class:

_tomcat = new Embedded();

String path = new
File(ServerProperties.getTomcatPath()).getAbsolutePath();
_tomcat.setCatalinaHome(path);

MemoryRealm memRealm = new MemoryRealm();
_tomcat.setRealm(memRealm);

// create an Engine
Engine baseEngine = _tomcat.createEngine();
baseEngine.setName("Engine");
baseEngine.setDefaultHost("localhost");

// create Host
Host baseHost = _tomcat.createHost("localhost", path + "/webapps");
baseEngine.addChild(baseHost);

// create root Context
Context rootCtx = _tomcat.createContext("", path + "/webapps/ROOT");
rootCtx.setReloadable(false);
rootCtx.addWelcomeFile("index.jsp");
baseHost.addChild(rootCtx);

// add new Engine to set of Engines for embedded server
_tomcat.addEngine(baseEngine);

// create Connector
Connector httpConnector = _tomcat.createConnector((InetAddress)null,
8080, false);

// add new Connector to set of Connectors for embedded server,
associated with Engine
_tomcat.addConnector(httpConnector);

// start operation
try
{
    _tomcat.start();
}
catch (org.apache.catalina.LifecycleException ex)
{
    // Todo: Handle tomcat exception
    ex.printStackTrace();
}

Here is the exception I get as a result of the null class loader:

javax.xml.parsers.FactoryConfigurationError: Provider
org.apache.xerces.jaxp.DocumentBuilderFactoryImpl not found
	at
javax.xml.parsers.DocumentBuilderFactory.newInstance(DocumentBuilderFact
ory.java:104)
	at
org.apache.commons.modeler.util.DomUtil.readXml(DomUtil.java:284)
	at
org.apache.commons.modeler.modules.MbeansDescriptorsDOMSource.execute(Mb
eansDescriptorsDOMSource.java:130)
	at
org.apache.commons.modeler.modules.MbeansDescriptorsDOMSource.loadDescri
ptors(MbeansDescriptorsDOMSource.java:120)
	at org.apache.commons.modeler.Registry.load(Registry.java:819)
	at
org.apache.commons.modeler.Registry.loadDescriptors(Registry.java:931)
	at
org.apache.commons.modeler.Registry.loadDescriptors(Registry.java:909)
	at
org.apache.commons.modeler.Registry.findDescriptor(Registry.java:992)
	at
org.apache.commons.modeler.Registry.findManagedBean(Registry.java:696)
	at
org.apache.commons.modeler.Registry.findManagedBean(Registry.java:1047)
	at
org.apache.commons.modeler.Registry.registerComponent(Registry.java:859)
	at
org.apache.catalina.loader.WebappLoader.init(WebappLoader.java:583)
	at
org.apache.catalina.loader.WebappLoader.start(WebappLoader.java:615)
	at
org.apache.catalina.core.StandardContext.start(StandardContext.java:3985
)
	at
org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1011)
	at
org.apache.catalina.core.StandardHost.start(StandardHost.java:718)
	at
org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1011)
	at
org.apache.catalina.core.StandardEngine.start(StandardEngine.java:437)
	at org.apache.catalina.startup.Embedded.start(Embedded.java:789)

Thanks,

Tim

---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org