Classpath issue between jetty-maven-plugin and tomcat-jdbc 8.0.9+ leading to ServiceConfigurationError

喜夏-厌秋 提交于 2019-12-10 01:17:17

问题


I'm working on an app using :

jetty-maven-plugin:9.3.2.v20150730
tomcat-jdbc:8.0.8 (which has tomcat-juli as dependency)

After trying to upgrade the tomcat-jdbc jar to any version beyond 8.0.9+ I get the following error:

java.util.ServiceConfigurationError: org.apache.juli.logging.Log: Provider org.eclipse.jetty.apache.jsp.JuliLog not a subtype

Looking the changelog between those 2 versions I've found something that looks suspicious:

"Add a simple ServiceLoader based discovery mechanism to the JULI LogFactory to make it easier to use JULI and Tomcat components that depend on JULI (such as Jasper) independently from Tomcat. Patch provided by Greg Wilkins. (markt)"

Also, I've found that a new system property was introduced in the Apache Tomcat JDBC Connection Pool:

org.apache.tomcat.jdbc.pool.onlyAttemptCurrentClassLoader

"Controls classloading of dynamic classes, such as JDBC drivers, interceptors and validators. If set to false, default value, the pool will first attempt to load using the current loader (i.e. the class loader that loaded the pool classes) and if class loading fails attempt to load using the thread context loader. Set this value to true, if you wish to remain backwards compatible with Apache Tomcat 8.0.8 and earlier, and only attempt the current loader. If not set then the default value is false."

Unfortunately, starting the plugin with jetty:run using this property didn't resolve the issue.

Any help would be appreciated! Thanks!

Stack trace and dependencies tree :

Caused by: 
java.util.ServiceConfigurationError: org.apache.juli.logging.Log: Provider org.eclipse.jetty.apache.jsp.JuliLog not a subtype
    at java.util.ServiceLoader.fail(ServiceLoader.java:239)
    at java.util.ServiceLoader.access$300(ServiceLoader.java:185)
    at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:376)
    at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
    at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
    at org.apache.juli.logging.LogFactory.(LogFactory.java:78)
    at org.apache.juli.logging.LogFactory.(LogFactory.java:66)
    at org.apache.tomcat.jdbc.pool.DataSourceFactory.(DataSourceFactory.java:58)
    at local.ristretto.persistence.datasource.mail.MailDataSourceConfiguration.dataSource(MailDataSourceConfiguration.java:31)
    at local.ristretto.persistence.datasource.mail.MailDataSourceConfiguration$$EnhancerBySpringCGLIB$$497970dd.CGLIB$dataSource$0()
    at local.ristretto.persistence.datasource.mail.MailDataSourceConfiguration$$EnhancerBySpringCGLIB$$497970dd$$FastClassBySpringCGLIB$$2ba2dde9.invoke()
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:309)
    at local.ristretto.persistence.datasource.mail.MailDataSourceConfiguration$$EnhancerBySpringCGLIB$$497970dd.dataSource()
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1119)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1014)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1120)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1044)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:464)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1119)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1014)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:956)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:747)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:434)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized(ContextHandler.java:798)
    at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:530)
    at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:771)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:342)
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1368)
    at org.eclipse.jetty.maven.plugin.JettyWebAppContext.startWebapp(JettyWebAppContext.java:320)
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1335)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:735)
    at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:259)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:511)
    at org.eclipse.jetty.maven.plugin.JettyWebAppContext.doStart(JettyWebAppContext.java:403)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:161)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.server.Server.start(Server.java:405)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:106)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.Server.doStart(Server.java:372)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.maven.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:457)
    at org.eclipse.jetty.maven.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:328)
    at org.eclipse.jetty.maven.plugin.JettyRunMojo.execute(JettyRunMojo.java:170)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:132)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:120)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:347)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:154)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:582)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:214)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:158)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
    at org.codehaus.classworlds.Launcher.main(Launcher.java:46)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
[INFO] |  +- org.springframework.data:spring-data-jpa:jar:1.8.2.RELEASE:compile               
[INFO] |  |  +- org.springframework.data:spring-data-commons:jar:1.10.2.RELEASE:compile       
[INFO] |  |  +- org.springframework:spring-orm:jar:4.1.7.RELEASE:compile                      
[INFO] |  |  |  \- org.springframework:spring-jdbc:jar:4.1.7.RELEASE:compile                  
[INFO] |  |  +- org.springframework:spring-tx:jar:4.1.7.RELEASE:compile                       
[INFO] |  |  \- org.aspectj:aspectjrt:jar:1.8.6:compile                                       
[INFO] |  +- org.postgresql:postgresql:jar:9.4-1202-jdbc42:compile                            
[INFO] |  +- org.apache.tomcat:tomcat-jdbc:jar:8.0.9:compile                                 
[INFO] |  |  \- org.apache.tomcat:tomcat-juli:jar:8.0.9:compile                              
[INFO] |  +- org.hibernate:hibernate-entitymanager:jar:5.0.1.Final:compile                    
[INFO] |  |  +- org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile                       
[INFO] |  |  +- org.hibernate:hibernate-core:jar:5.0.1.Final:compile                          
[INFO] |  |  |  +- antlr:antlr:jar:2.7.7:compile                                              
[INFO] |  |  |  \- org.jboss:jandex:jar:1.2.2.Final:compile                                   
[INFO] |  |  +- dom4j:dom4j:jar:1.6.1:compile                                                 
[INFO] |  |  |  \- xml-apis:xml-apis:jar:1.0.b2:compile                                       
[INFO] |  |  +- org.hibernate.common:hibernate-commons-annotations:jar:5.0.0.Final:compile    
[INFO] |  |  +- org.hibernate.javax.persistence:hibernate-jpa-2.1-api:jar:1.0.0.Final:compile 
[INFO] |  |  +- org.apache.geronimo.specs:geronimo-jta_1.1_spec:jar:1.1.1:compile             
[INFO] |  |  \- org.javassist:javassist:jar:3.18.1-GA:compile                                 
[INFO] |  \- com.fasterxml.jackson.core:jackson-databind:jar:2.6.1:compile                    
[INFO] |     +- com.fasterxml.jackson.core:jackson-annotations:jar:2.6.1:compile              
[INFO] |     \- com.fasterxml.jackson.core:jackson-core:jar:2.6.1:compile                     

[INFO] |  +- org.slf4j:jcl-over-slf4j:jar:1.7.12:compile                                      
[INFO] |  +- org.slf4j:jul-to-slf4j:jar:1.7.12:compile                                        
[INFO] |  +- org.slf4j:log4j-over-slf4j:jar:1.7.12:compile                                    
[INFO] |  +- org.slf4j:slf4j-api:jar:1.7.12:compile                                           
[INFO] |  +- ch.qos.logback:logback-classic:jar:1.1.3:compile                                 
[INFO] |  |  \- ch.qos.logback:logback-core:jar:1.1.3:compile                                 
[INFO] |  +- org.wicketstuff:wicketstuff-logback:jar:6.20.0:compile                           
[INFO] |  +- org.apache.commons:commons-lang3:jar:3.4:compile                                 
[INFO] |  +- org.apache.commons:commons-collections4:jar:4.0:compile                          
[INFO] |  +- commons-io:commons-io:jar:2.4:compile                                            
[INFO] |  +- commons-codec:commons-codec:jar:1.10:compile                                     
[INFO] |  +- commons-beanutils:commons-beanutils:jar:1.9.2:compile                            
[INFO] |  |  \- commons-collections:commons-collections:jar:3.2.1:compile                     
[INFO] |  \- com.google.guava:guava:jar:18.0:compile                                          
[INFO] +- junit:junit:jar:4.12:test                                                           
[INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test                                          
[INFO] +- org.springframework:spring-test:jar:4.1.7.RELEASE:test                              
[INFO] |  \- org.springframework:spring-core:jar:4.1.7.RELEASE:compile                        
[INFO] +- org.springframework:spring-web:jar:4.1.7.RELEASE:compile                            
[INFO] |  +- org.springframework:spring-aop:jar:4.1.7.RELEASE:compile                         
[INFO] |  |  \- aopalliance:aopalliance:jar:1.0:compile                                       
[INFO] |  +- org.springframework:spring-beans:jar:4.1.7.RELEASE:compile                       
[INFO] |  \- org.springframework:spring-context:jar:4.1.7.RELEASE:compile                     
[INFO] |     \- org.springframework:spring-expression:jar:4.1.7.RELEASE:compile               
[INFO] \- javax:javaee-web-api:jar:7.0:provided

回答1:


The spring boot starter web dependency will include tomcat by default. This will confuse jetty when you start it, since it uses different versions of the juli lib.

Simply fix in your pom.xml, exlude the starter-tomcat and separately include the jetty dependency:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>



回答2:


It appears, that this is caused by Jetty using a modified Apache JSP package Jasper. It has its own version of Juli logging (check lib/apache-jsp/org.mortbay.jasper.apache-jsp-8.0.27.jar under Jetty home directory) which seems to cause all the confusion. I think, that Jetty's default webapp class loading logic causes Juli LogFactory from your webapp to be loaded everytime that class is requested. It's all good and dandy when that LogFactory has to load tomcat-jdbc classes. It gets tricky when it gets passed Jetty's modified Jasper classes, because it realises that there are type conflicts.

How you can solve this? I think there are 2 ways to do so:

1. Change Jetty webapp classloader logic

You can modify classloader logic, to always delegate class loading to parent classloader. You just need to call setParentLoaderPriority(true) on particular WebAppContext. You can do that either by Jetty configuration or by including jetty-web.xml file with your war.

2. Exclude tomcat-juli dependency

Using Maven's Dependency exclusions you can skip any transitive dependency you do not like. So just include tomcat-jdbc without tomcat-juli and you're done.

The only problem is that both solutions force you to use Jetty's modified Juli package. Haven't seen a problem with such scenario yet, but I guess at some point you might find you're missing some feature, because Jetty's modified Juli wasn't synced with Apache latest version.



来源:https://stackoverflow.com/questions/32643530/classpath-issue-between-jetty-maven-plugin-and-tomcat-jdbc-8-0-9-leading-to-ser

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!