Spring 使用外部 JAR 启动时出现 NoClassDefFoundError
Spring Boot with External JAR gets NoClassDefFoundError
所以我的主项目中有一组子项目。第一个项目(在下面的示例中称为 mainCode
)实现了应用程序的全部功能。但是,WidgetAImpl
和 WidgetBImpl
被分成单独的子项目,以便在需要修复时可以独立部署。 WidgetAImpl
和 WidgetBImpl
类 与接口 WidgetInterface
.
位于同一个包中
项目布局如下:
project
+ mainCode
+ /src/main/java/com/mycompany/myproject/Application.java
+ /src/main/java/com/mycompany/myproject/AppConfig.java
+ /src/main/java/com/mycompany/myproject/widgets/WidgetInterface.java
+ widgets
+ WidgetA
+ /src/main/java/com/mycompany/myproject/widgets/WidgetAImpl.java
+ WidgetB
+ /src/main/java/com/mycompany/myproject/widgets/WidgetBImpl.java
我 gradle 以这样的方式构建这些 mainCode
项目成为我们的 war 文件以部署到 tomcat 并且每个小部件都变成一个 jar文件。目标是将 jar 文件添加到 tomcat 的类路径中,并单独部署 war 文件。我花了一天时间 Gradle 来构建 WidgetAImpl
项目,方法是将 mainCode
项目声明为依赖项。所以 Gradle 现在可以正确构建它们,我有一个 mainCode.war
和一个 WidgetAImpl.jar
和一个 WidgetBImpl.jar
文件。在实现中,小部件都与一个自动装配的 HashMap 聚集在一起,因此所有已实现的小部件都在 运行 时间在单个 HashMap 中创建。我已经通过 catalina.properties sharedLoader 属性.
将小部件添加到 tomcat 的类路径中
我的问题是,当我将 war 文件部署到 tomcat 时,出现以下错误(针对 space 进行了修剪):
2017-11-15 21:55:39.841 WARN 16687 --- [nio-8443-exec-4] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.scheduling.annotation.ProxyAsyncConfiguration': Unsatisfied dependency expressed through method 'setConfigurers' parameter 0; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [com.mycompany.myproject.widgets.WidgetAImpl] for bean with name 'WidgetAImpl' defined in URL [jar:file:/mycompany/libs/WidgetAImpl.jar!/com/mycompany/myproject/widgets/WidgetAImpl.class]: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: com/mycompany/myproject/widgets/WidgetInterface
2017-11-15 21:55:39.845 ERROR 16687 --- [nio-8443-exec-4] o.s.b.f.s.DefaultListableBeanFactory : Destroy method on bean with name 'org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor' threw an exception
java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3633386f: startup date [Wed Nov 15 21:55:38 UTC 2017]; root of context hierarchy
at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:404) [spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.context.support.ApplicationListenerDetector.postProcessBeforeDestruction(ApplicationListenerDetector.java:97) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:253) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:954) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:961) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1033) [spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:555) [spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) [spring-boot-1.4.2.RELEASE.jar:1.4.2.RELEASE]
...
Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [com.mycompany.myproject.widgets.WidgetAImpl] for bean with name 'WidgetAImpl' defined in URL [jar:file:/mycompany/libs/WidgetAImpl.jar!/com/mycompany/myproject/widgets/WidgetAImpl.class]: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: com/mycompany/myproject/widgets/WidgetInterface
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1364) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:639) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:607) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1456) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:420) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:390) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors(BeanFactoryUtils.java:220) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1243) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1164) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1089) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1059) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:663) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
... 68 common frames omitted
Caused by: java.lang.NoClassDefFoundError: com/mycompany/myproject/widgets/WidgetInterface
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_144]
at java.lang.ClassLoader.defineClass(Unknown Source) ~[na:1.8.0_144]
at java.security.SecureClassLoader.defineClass(Unknown Source) ~[na:1.8.0_144]
at java.net.URLClassLoader.defineClass(Unknown Source) ~[na:1.8.0_144]
at java.net.URLClassLoader.access0(Unknown Source) ~[na:1.8.0_144]
at java.net.URLClassLoader.run(Unknown Source) ~[na:1.8.0_144]
at java.net.URLClassLoader.run(Unknown Source) ~[na:1.8.0_144]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_144]
at java.net.URLClassLoader.findClass(Unknown Source) ~[na:1.8.0_144]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[na:1.8.0_144]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[na:1.8.0_144]
at java.lang.Class.forName0(Native Method) ~[na:1.8.0_144]
at java.lang.Class.forName(Unknown Source) ~[na:1.8.0_144]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1271) ~[catalina.jar:8.5.20]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119) ~[catalina.jar:8.5.20]
at org.springframework.util.ClassUtils.forName(ClassUtils.java:250) ~[spring-core-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:394) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1408) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1353) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
... 79 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.mycompany.myproject.widgets.WidgetInterface
at java.net.URLClassLoader.findClass(Unknown Source) ~[na:1.8.0_144]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[na:1.8.0_144]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[na:1.8.0_144]
... 98 common frames omitted
(完整异常堆栈跟踪:https://pastebin.com/KwaNGaeN)
由此看来Spring找不到我的WidgetInterface。但是,我已经确认 war 文件中的 WidgetInterface 类文件 是 。此外,它与 WidgetAImpl 和 WidgetBImpl 是相同的 java 包(即使它们位于不同的文件中)。为什么它看不到 WidgetInterface?
你能用 WidgetInterface.java
创建 common
或 base
模块吗?将其作为小部件添加到 Tomcat。然后所有其他罐子, war 可以依赖那个公共部分。 Tomcat 将有清晰的路径如何加载它,其他模块使用什么。
所以我的主项目中有一组子项目。第一个项目(在下面的示例中称为 mainCode
)实现了应用程序的全部功能。但是,WidgetAImpl
和 WidgetBImpl
被分成单独的子项目,以便在需要修复时可以独立部署。 WidgetAImpl
和 WidgetBImpl
类 与接口 WidgetInterface
.
项目布局如下:
project
+ mainCode
+ /src/main/java/com/mycompany/myproject/Application.java
+ /src/main/java/com/mycompany/myproject/AppConfig.java
+ /src/main/java/com/mycompany/myproject/widgets/WidgetInterface.java
+ widgets
+ WidgetA
+ /src/main/java/com/mycompany/myproject/widgets/WidgetAImpl.java
+ WidgetB
+ /src/main/java/com/mycompany/myproject/widgets/WidgetBImpl.java
我 gradle 以这样的方式构建这些 mainCode
项目成为我们的 war 文件以部署到 tomcat 并且每个小部件都变成一个 jar文件。目标是将 jar 文件添加到 tomcat 的类路径中,并单独部署 war 文件。我花了一天时间 Gradle 来构建 WidgetAImpl
项目,方法是将 mainCode
项目声明为依赖项。所以 Gradle 现在可以正确构建它们,我有一个 mainCode.war
和一个 WidgetAImpl.jar
和一个 WidgetBImpl.jar
文件。在实现中,小部件都与一个自动装配的 HashMap 聚集在一起,因此所有已实现的小部件都在 运行 时间在单个 HashMap 中创建。我已经通过 catalina.properties sharedLoader 属性.
我的问题是,当我将 war 文件部署到 tomcat 时,出现以下错误(针对 space 进行了修剪):
2017-11-15 21:55:39.841 WARN 16687 --- [nio-8443-exec-4] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.scheduling.annotation.ProxyAsyncConfiguration': Unsatisfied dependency expressed through method 'setConfigurers' parameter 0; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [com.mycompany.myproject.widgets.WidgetAImpl] for bean with name 'WidgetAImpl' defined in URL [jar:file:/mycompany/libs/WidgetAImpl.jar!/com/mycompany/myproject/widgets/WidgetAImpl.class]: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: com/mycompany/myproject/widgets/WidgetInterface
2017-11-15 21:55:39.845 ERROR 16687 --- [nio-8443-exec-4] o.s.b.f.s.DefaultListableBeanFactory : Destroy method on bean with name 'org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor' threw an exception
java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3633386f: startup date [Wed Nov 15 21:55:38 UTC 2017]; root of context hierarchy
at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:404) [spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.context.support.ApplicationListenerDetector.postProcessBeforeDestruction(ApplicationListenerDetector.java:97) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:253) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:954) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:961) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1033) [spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:555) [spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) [spring-boot-1.4.2.RELEASE.jar:1.4.2.RELEASE]
...
Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [com.mycompany.myproject.widgets.WidgetAImpl] for bean with name 'WidgetAImpl' defined in URL [jar:file:/mycompany/libs/WidgetAImpl.jar!/com/mycompany/myproject/widgets/WidgetAImpl.class]: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: com/mycompany/myproject/widgets/WidgetInterface
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1364) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:639) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:607) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1456) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:420) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:390) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors(BeanFactoryUtils.java:220) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1243) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1164) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1089) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1059) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:663) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
... 68 common frames omitted
Caused by: java.lang.NoClassDefFoundError: com/mycompany/myproject/widgets/WidgetInterface
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_144]
at java.lang.ClassLoader.defineClass(Unknown Source) ~[na:1.8.0_144]
at java.security.SecureClassLoader.defineClass(Unknown Source) ~[na:1.8.0_144]
at java.net.URLClassLoader.defineClass(Unknown Source) ~[na:1.8.0_144]
at java.net.URLClassLoader.access0(Unknown Source) ~[na:1.8.0_144]
at java.net.URLClassLoader.run(Unknown Source) ~[na:1.8.0_144]
at java.net.URLClassLoader.run(Unknown Source) ~[na:1.8.0_144]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_144]
at java.net.URLClassLoader.findClass(Unknown Source) ~[na:1.8.0_144]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[na:1.8.0_144]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[na:1.8.0_144]
at java.lang.Class.forName0(Native Method) ~[na:1.8.0_144]
at java.lang.Class.forName(Unknown Source) ~[na:1.8.0_144]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1271) ~[catalina.jar:8.5.20]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119) ~[catalina.jar:8.5.20]
at org.springframework.util.ClassUtils.forName(ClassUtils.java:250) ~[spring-core-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:394) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1408) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1353) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
... 79 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.mycompany.myproject.widgets.WidgetInterface
at java.net.URLClassLoader.findClass(Unknown Source) ~[na:1.8.0_144]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[na:1.8.0_144]
at java.lang.ClassLoader.loadClass(Unknown Source) ~[na:1.8.0_144]
... 98 common frames omitted
(完整异常堆栈跟踪:https://pastebin.com/KwaNGaeN)
由此看来Spring找不到我的WidgetInterface。但是,我已经确认 war 文件中的 WidgetInterface 类文件 是 。此外,它与 WidgetAImpl 和 WidgetBImpl 是相同的 java 包(即使它们位于不同的文件中)。为什么它看不到 WidgetInterface?
你能用 WidgetInterface.java
创建 common
或 base
模块吗?将其作为小部件添加到 Tomcat。然后所有其他罐子, war 可以依赖那个公共部分。 Tomcat 将有清晰的路径如何加载它,其他模块使用什么。