Проблема класса с каналом Jetty-maven-plugin и tomcat-jdbc 8.0.9+, приводящая к ServiceConfigurationError
Я работаю над приложением, используя:
Причал-Maven-плагин: 9.3.2.v20150730
tomcat-jdbc: 8.0.8 (который имеет зависимость от tomcat-juli)
После попытки обновить банку tomcat-jdbc до любой версии, превышающей 8.0.9+, я получаю следующую ошибку:
java.util.ServiceConfigurationError: org.apache.juli.logging.Log: Поставщик org.eclipse.jetty.apache.jsp.JuliLog не подтип
В поисках изменений между этими двумя версиями я обнаружил что-то подозрительное:
"Добавить простой механизм обнаружения на основе ServiceLoader в JULI LogFactory, чтобы упростить использование компонентов JULI и Tomcat, которые зависят от JULI (например, Jasper) независимо от Tomcat. Патч предоставлен Грегом Уилкинсом (markt)"
Кроме того, я обнаружил, что в пуле соединений Apache Tomcat JDBC было добавлено новое системное свойство:
org.apache.tomcat.jdbc.pool.onlyAttemptCurrentClassLoader
"Контролирует загрузку классов динамических классов, таких как драйверы JDBC, перехватчики и валидаторы. Если установлено значение false, значение по умолчанию, пул сначала попытается загрузить с использованием текущего загрузчика (т.е. загрузчик классов, загружающий классы пула) и если загрузка классов не удается загрузить с помощью загрузчика контекста потока. Установите это значение в значение true, если вы хотите оставаться обратно совместимым с Apache Tomcat 8.0.8 и более ранними версиями и только пытаться использовать текущий загрузчик. Если он не установлен, значение по умолчанию равно ложный."
К сожалению, запуск плагина с приложением: запуск с использованием этого свойства не разрешил проблему.
Любая помощь будет оценена! Спасибо!
Дерево трассировки стеков и зависимостей:
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
В зависимости от загрузочной веб-зависимости spring будет включен tomcat по умолчанию. Это будет путать причал, когда вы начнете его, поскольку он использует разные версии juli lib.
Просто исправьте свой pom.xml, исключите стартер-кошку и отдельно включите зависимость причала:
<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 с использованием модифицированного пакета Jashper Apache JSP. У него есть своя версия регистрации Juli (проверьте lib/apache-jsp/org.mortbay.jasper.apache-jsp-8.0.27.jar
в домашнем каталоге Jetty), который, похоже, вызывает всю путаницу. Я думаю, что Jetclock defaultappappa логика загрузки классов заставляет Juli LogFactory
из вашего webapp загружаться каждый раз, когда запрашивается этот класс. Все это хорошо и денди, когда LogFactory
должен загружать классы tomcat-jdbc
. Это становится сложным, когда он получает переданные Jetty классы Jasper, потому что он понимает, что существуют конфликты типов.
Как вы можете это решить? Я думаю, что есть два способа сделать это:
1. Измените логику загрузчика classload Jetty webapp
Вы можете модифицировать логику загрузчика классов, чтобы всегда делегировать загрузку классов родительскому загрузчику классов. Вам просто нужно вызвать setParentLoaderPriority(true)
на конкретном WebAppContext
. Вы можете сделать это либо с помощью конфигурации Jetty, либо путем включения файла jetty-web.xml
в вашу войну.
2. Исключить зависимость tomcat-juli
Используя Maven Исключения зависимостей, вы можете пропустить любую транзитивную зависимость, которая вам не нравится. Так что просто включите tomcat-jdbc
без tomcat-juli
, и все готово.
Единственная проблема заключается в том, что оба решения заставляют вас использовать модифицированный Juli пакет Jetty. Пока не было проблемы с таким сценарием, но, наверное, в какой-то момент вы можете обнаружить, что вам не хватает какой-либо функции, потому что Jetty, модифицированная Juli, не была синхронизирована с последней версией Apache.