java - 带有外部 JAR 的 Spring Boot 获取 NoClassDefFoundError

标签 java tomcat spring-boot jar classnotfoundexception

所以我的主项目中有一组子项目。第一个项目(在下面的示例中称为 mainCode)实现了应用程序的全部功能。但是,WidgetAImplWidgetBImpl 被分离到单独的子项目中,以便在需要修复时可以独立部署。 WidgetAImplWidgetBImpl 类位于与接口(interface) 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 项目成为我们部署到 tomcat 的 war 文件,每个小部件都变成一个 jar 文件。目标是将 jar 文件添加到 tomcat 的类路径中,并单独部署 war 文件。我花了一天时间让 Gradle 通过声明 mainCode 项目为依赖项来构建 WidgetAImpl 项目。所以 Gradle 现在可以正确构建它们,我有一个 mainCode.war 和一个 WidgetAImpl.jar 和一个 WidgetBImpl.jar 文件。在实现中,小部件都与一个 Autowiring 的 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 类文件 war 文件中。此外,它与 WidgetAImpl 和 WidgetBImpl 是同一个 java 包(即使它们位于不同的文件中)。为什么它看不到 WidgetInterface?

最佳答案

你能用那个 WidgetInterface.java 创建 commonbase 模块吗?将它作为小部件添加到 Tomcat。然后所有其他 jar , war 都可以依靠那个,共同的部分。 Tomcat 将有清晰的路径如何加载它,其他模块使用什么。

关于java - 带有外部 JAR 的 Spring Boot 获取 NoClassDefFoundError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47318650/

相关文章:

java - 通过使用 request.getParameter 和 multipart 来获取值

jakarta-ee - 带有 unpackWARs ="false"的 Tomcat 无法部署基于 CDI Weld 的应用程序

java.lang.NoClassDefFoundError : apache-tomcat-7. 0.25

amazon-web-services - 在 AWS elasticbeanstalk 中使用 .ebextensions 配置 nginx 配置文件未找到

spring-boot - gradle build --warning-mode =不建议使用的所有警告注释处理器而是使用处理器路径

java - 谓词#and : any way to access the internal predicates?

Java-如何在读取Excel文件后在数据库表中插入行

java - 将图像发送到浏览器客户端

tomcat - Itext 5.5 将 RTL 语言(阿拉伯语)的 HTML 转换为 PDF 不适用于 tomcat

java - Spring Batch 远程分区