【问题标题】:Classpath issue between jetty-maven-plugin and tomcat-jdbc 8.0.9+ leading to ServiceConfigurationErrorjetty-maven-plugin 和 tomcat-jdbc 8.0.9+ 之间的类路径问题导致 ServiceConfigurationError
【发布时间】:2015-12-15 02:26:51
【问题描述】:

我正在使用:

jetty-maven-plugin:9.3.2.v20150730
tomcat-jdbc:8.0.8(依赖tomcat-juli)

在尝试将 tomcat-jdbc jar 升级到 8.0.9+ 之后的任何版本后,我收到以下错误:

java.util.ServiceConfigurationError: org.apache.juli.logging.Log: 提供者 org.eclipse.jetty.apache.jsp.JuliLog 不是子类型

查看这两个版本之间的更新日志,我发现了一些可疑的东西:

"在 JULI LogFactory 中添加一个简单的基于 ServiceLoader 的发现机制,使依赖于 JULI 的 JULI 和 Tomcat 组件(如 Jasper)更容易独立于 Tomcat。Greg Wilkins 提供的补丁。(markt) "

另外,我发现 Apache Tomcat JDBC 连接池中引入了一个新的系统属性:

org.apache.tomcat.jdbc.pool.onlyAttemptCurrentClassLoader

"控制动态类的类加载,例如 JDBC 驱动程序、拦截器和验证器。如果设置为 false,默认值,池将首先尝试使用当前加载器(即加载池的类加载器)加载classes) 并且如果类加载失败尝试使用线程上下文加载器加载。将此值设置为 true,如果您希望保持与 Apache Tomcat 8.0.8 和更早版本的向后兼容,并且仅尝试当前加载器。如果未设置,则默认值为 false。”

不幸的是,使用 jetty:run 启动插件并没有解决问题。

任何帮助将不胜感激!谢谢!

堆栈跟踪和依赖树:

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

【问题讨论】:

  • 添加了堆栈跟踪和依赖树@ChristopherSchultz
  • 您是否已将 tomcat-juli.jar 从 Tomcat 的 conf/ 目录复制到您的 Web 应用程序的 WEB-INF/lib 目录,或任何其他可能在您的 Web 应用程序的类路径中结束的位置?
  • 是的,今天它在我的 pom.xml 中用 compile 范围声明。我可以安全地将其更改为提供吗?
  • 我不是 Maven 专家,但 tomcat-juli.jar 实际上是 Tomcat 提供的,所以你根本不需要提及它,除非你需要针对它进行构建。

标签: java maven jetty tomcat-jdbc tomcat-juli


【解决方案1】:

spring boot starter web 依赖默认会包含tomcat。当你启动它时,这会混淆 jetty,因为它使用不同版本的 juli lib。

只需在你的 pom.xml 中修复,排除 starter-tomcat 并单独包含 jetty 依赖项:

    <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】:

    看来,这是由 Jetty 使用修改后的 Apache JSP 包 Jasper 引起的。它有自己的 Juli 日志版本(检查 Jetty 主目录下的 lib/apache-jsp/org.mortbay.jasper.apache-jsp-8.0.27.jar),这似乎引起了所有的混乱。我认为,Jetty 的默认 webapp class loading logic 会导致您的 webapp 中的 Juli LogFactory 在每次请求该类时被加载。当 LogFactory 必须加载 tomcat-jdbc 类时,这一切都很好。当它通过 Jetty 修改的 Jasper 类时会变得很棘手,因为它意识到存在类型冲突。

    如何解决这个问题?我认为有两种方法可以做到这一点:

    1.更改 Jetty webapp 类加载器逻辑

    您可以修改类加载器逻辑,始终将类加载委托给父类加载器。您只需要在特定的WebAppContext 上致电setParentLoaderPriority(true)。您可以通过 Jetty 配置或在您的战争中包含 jetty-web.xml 文件来做到这一点。

    2。排除tomcat-juli依赖

    使用 Maven 的Dependency exclusions,您可以跳过任何您不喜欢的传递依赖。因此,只需包含 tomcat-jdbc 而不包含 tomcat-juli 即可。

    唯一的问题是这两种解决方案都强制您使用 Jetty 修改后的 Juli 包。还没有看到这种情况的问题,但我想在某些时候你可能会发现你缺少一些功能,因为 Jetty 修改后的 Juli 没有与 Apache 最新版本同步。

    【讨论】:

    • 请注意,如果您使用setParentLoaderPriority(true),您正在从 Servlet 规范类加载器行为(webapp 优先)切换到 Java 规范类加载器行为(父类优先)。如果您的 web 应用程序需要 Servlet 规范行为,那么这不是解决此问题的正确方法。
    • 使用第二个方法,我的 JUnit 失败了。
    【解决方案3】:

    如果不是春季项目

    这是我在 pom.xml 中提供的排除项:

            <dependency>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.4.24.v20191120</version>
                 <exclusions>
                    <exclusion>
                        <groupId>org.eclipse.jetty</groupId>
                        <artifactId>apache-jsp</artifactId>
                    </exclusion>
                 </exclusions>
            </dependency>
    

    还提供了插件:

               <plugin>
                    <groupId>org.eclipse.jetty</groupId>
                    <artifactId>jetty-maven-plugin</artifactId>
                    <version>9.4.24.v20191120</version>
    
                    <configuration>
                        <scanIntervalSeconds>10</scanIntervalSeconds>
                        <webApp>
                            <contextPath>/ezops-preprocessor</contextPath>
                        </webApp>
                    </configuration>
    
                </plugin>
    

    使用上述排除项 apache-jsp(Jule Logging),我没有得到该异常。

    希望这会有所帮助。!!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-30
      • 1970-01-01
      • 2019-01-25
      • 1970-01-01
      • 1970-01-01
      • 2012-11-27
      • 1970-01-01
      • 2023-03-25
      相关资源
      最近更新 更多