gradle-tomcat-plugin
gradle-tomcat-plugin copied to clipboard
RFE: Support web apps with custom ClassLoaders
Currently gradle-tomcat-plugin
always uses org.apache.catalina.loader.WebappLoader
as ClassLoader
for the web app (see BaseTomcat7xPlusImpl.groovy#L48 for Tomcat 7/8 and Tomcat6xServer.groovy#L56 for Tomcat 6). This does not work if web app specifies custom ClassLoader
to be used as part of its context.xml
, e.g.:
<Context>
<Loader loaderClass="test.CustomClassLoader" delegate="false" />
</Context>
I've create sample project to reproduce this issue https://github.com/vyazelenko/gradle-tomcat-plugin-custom-classloader. When I run ./gradlew tomcatRun
in this project I get the following error:
./gradlew tomcatRun
:compileJava
:processResources UP-TO-DATE
:classes
:custom-classloader:compileJava
:custom-classloader:processResources UP-TO-DATE
:custom-classloader:classes
:custom-classloader:jar
:tomcatRunEnd event threw exception
java.lang.ClassNotFoundException: org.apache.tomcat.util.descriptor.web.ServletDef
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1308)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1142)
at org.apache.tomcat.util.IntrospectionUtils.callMethod1(IntrospectionUtils.java:355)
at org.apache.tomcat.util.digester.SetNextRule.end(SetNextRule.java:145)
at org.apache.tomcat.util.digester.Digester.endElement(Digester.java:956)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1783)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2970)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1451)
at org.apache.tomcat.util.descriptor.web.WebXmlParser.parseWebXml(WebXmlParser.java:120)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1116)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:780)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:305)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:95)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5154)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Parse error in application web.xml file at file:/P:/Projects/oss/gradle-tomcat-plugin-custom-classloader/src/main/webapp/WEB-INF/web.xml
org.xml.sax.SAXParseException; systemId: file:/P:/Projects/oss/gradle-tomcat-plugin-custom-classloader/src/main/webapp/WEB-INF/web.xml; lineNumber: 9; columnNumber: 15; Error at (9, 15) : org.apache.tomcat.util.descriptor.web.ServletDef
at org.apache.tomcat.util.digester.Digester.createSAXException(Digester.java:1908)
at org.apache.tomcat.util.digester.Digester.createSAXException(Digester.java:1940)
at org.apache.tomcat.util.digester.Digester.endElement(Digester.java:959)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1783)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2970)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1451)
at org.apache.tomcat.util.descriptor.web.WebXmlParser.parseWebXml(WebXmlParser.java:120)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1116)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:780)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:305)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:95)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5154)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: org.apache.tomcat.util.descriptor.web.ServletDef
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1308)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1142)
at org.apache.tomcat.util.IntrospectionUtils.callMethod1(IntrospectionUtils.java:355)
at org.apache.tomcat.util.digester.SetNextRule.end(SetNextRule.java:145)
at org.apache.tomcat.util.digester.Digester.endElement(Digester.java:956)
... 25 more
Occurred at line 9 column 15
Marking this application unavailable due to previous error(s)
One or more components marked the context as not correctly configured
Context [/gradle-tomcat-plugin-custom-classloader] startup failed due to previous errors
JDBC driver de-registration failed for web application [gradle-tomcat-plugin-custom-classloader]
java.lang.NullPointerException
at org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc(WebappClassLoaderBase.java:1609)
at org.apache.catalina.loader.WebappClassLoaderBase.clearReferences(WebappClassLoaderBase.java:1544)
at org.apache.catalina.loader.WebappClassLoaderBase.stop(WebappClassLoaderBase.java:1496)
at org.apache.catalina.loader.WebappLoader.stopInternal(WebappLoader.java:446)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:224)
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5517)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:224)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:159)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Started Tomcat Server
The Server is running at http://localhost:8080/gradle-tomcat-plugin-custom-classloader
However if I comment out context.xml#L3 I can start web app without error. But of course it will not run properly as it expects test.CustomClassLoader
to be used, i.e. the java.lang.IllegalStateException: Invalid ClassLoader used: WebappClassLoader
will be thrown:
If proper ClassLoader will be used then servlet should print the following message: