Details

Description

When one has a custom factory class deployed under domain/lib and a resource is created which uses this factory to create an injectable class located in a webapp, then the following (or similar) exception is thrown during appserver startup:

javax.naming.CommunicationException: serial context communication ex [Root exception is java.lang.ClassNotFoundException: a.Config]
at com.sun.enterprise.naming.SerialContext.lookup(SerialContext.java:438)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.sun.enterprise.naming.NamingManagerImpl.bindObjects(NamingManagerImpl.java:391)
at com.sun.enterprise.web.WebModuleContextConfig.configureResource(WebModuleContextConfig.java:227)
at com.sun.enterprise.web.WebModuleContextConfig.lifecycleEvent(WebModuleContextConfig.java:167)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:159)
at org.apache.catalina.core.StandardContext.init(StandardContext.java:6476)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4977)
at com.sun.enterprise.web.WebModule.start(WebModule.java:353)
at com.sun.enterprise.web.LifecycleStarter.doRun(LifecycleStarter.java:58)
at com.sun.appserv.management.util.misc.RunnableBase.runSync(RunnableBase.java:304)
at com.sun.appserv.management.util.misc.RunnableBase.run(RunnableBase.java:341)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassNotFoundException: a.Config
at com.sun.enterprise.util.ConnectorClassLoader.loadClass(ConnectorClassLoader.java:222)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at a.ConfigFactory.getObjectInstance(ConfigFactory.java:21)
at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:304)
at com.sun.enterprise.naming.SerialContext.lookup(SerialContext.java:414)
... 17 more

The cause is that when the LifecycleStarter task is created in VirtualServer then the current thread's contextClassLoader is the ConnectorClassLoader and so that's the one which gets inherited by the RunnableBase.

I think if an injectable resource class is allowed to be local to a webapp then the appropriate classLoader should be utilized when doing any kind of work with the factories.

Proposed solution: VirtualServer might set the current thread's contextClassLoader to the webapp's loader every time it creates a runnable task for a WebModule and then set it back to the old value.

Couldn't reproduce it in v3.1. Attached are the factory jar under domain/lib and the webapp and here's the resource entry in domain.xml: