使用外部 JAR 的 Spring Boot 出现 NoClassDefFoundError

问题描述 投票:0回答:2

所以我的主项目中有一组子项目。第一个项目(在下面的示例中称为

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
文件。在实现中,小部件都通过 Autowired HashMap 聚集在一起,以便在运行时在单个 HashMap 中创建所有实现的小部件。我已通过 catalina.properties sharedLoader 属性将小部件添加到 tomcat 的类路径中。

我的问题是,当我将 war 文件部署到 tomcat 时,出现以下错误(已修剪空间):

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.access$100(Unknown Source) ~[na:1.8.0_144]
    at java.net.URLClassLoader$1.run(Unknown Source) ~[na:1.8.0_144]
    at java.net.URLClassLoader$1.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。但是,我已经确认 WidgetInterface 类文件is 在 war 文件中。此外,它与 WidgetAImpl 和 WidgetBImpl 是相同的 java 包(即使它们位于单独的文件中)。为什么看不到WidgetInterface?

java tomcat spring-boot jar classnotfoundexception
2个回答
1
投票

您可以使用

common
创建
base
WidgetInterface.java
模块吗?将其作为小部件添加到 Tomcat。然后所有其他罐子和战争都可以依赖那个公共部分。 Tomcat 将有干净的路径如何加载它,其他模块使用什么。


0
投票

这在 IntelliJ IDE 中对我有用。

请在应用程序内创建文件夹作为 libs 并放入 jar。

repositories {
    maven {
        flatDir {
            dirs "app/libs"
        }
    }
}



dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}
© www.soinside.com 2019 - 2024. All rights reserved.