杰克逊数据绑定类路径问题

2022-09-04 00:53:57

我有一个弹簧启动应用程序,当我在本地使用“mvn clean install”进行部署时,它可以正常工作,但是当通过Jenkin生成战争时,它会抛出以下错误。

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'objectMapper' defined in class path resource [com/test/common/TestRestConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.fasterxml.jackson.databind.ObjectMapper]: Factory method 'objectMapper' threw exception; nested exception is java.lang.NoClassDefFoundError: Could not initialize class com.fasterxml.jackson.databind.SerializationConfig
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1192)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545)
        ... 62 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.fasterxml.jackson.databind.ObjectMapper]: Factory method 'objectMapper' threw exception; nested exception is java.lang.NoClassDefFoundError: Could not initialize class com.fasterxml.jackson.databind.SerializationConfig
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
        ... 74 common frames omitted
Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.fasterxml.jackson.databind.SerializationConfig
        at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:535)
        at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:452)

我只是尝试使用超越比较来比较2个war文件,除了用于编译的JDK次要版本之外,我没有看到任何差异。

我试图在我的本地构建和jenkin版本中搜索序列化配置.class,

以下命令的输出为:

find . -type f -name '*.jar' -print0 |  xargs -0 -I '{}' sh -c 'jar tf {} | grep SerializationConfig.class &&  echo {}'

局部战争 O/P :-

com/fasterxml/jackson/databind/SerializationConfig.class
./jackson-databind-2.7.3.jar
org/codehaus/jackson/map/SerializationConfig.class
./jackson-mapper-asl-1.9.13.jar
com/fasterxml/jackson/databind/SerializationConfig.class
./jersey-all-2.18.jar

詹金战争O / P :-

com/fasterxml/jackson/databind/SerializationConfig.class
./jersey-all-2.18.jar
org/codehaus/jackson/map/SerializationConfig.class
./jackson-mapper-asl-1.9.13.jar
com/fasterxml/jackson/databind/SerializationConfig.class
./jackson-databind-2.7.3.jar

基本上,我将 ObjectMapper 注入到我的 TestRestConfiguration 类中,如下所示,

@Inject
    private ObjectMapper objectMapper;

不确定,为什么通过Jenkin生成的war文件会引起问题。

任何这方面的帮助将不胜感激。


答案 1

您似乎正在从两个不同的 jar 文件依赖项中提取相同的类 (SerializationConfig)。从你的问题中,很明显,com.fasterxml.jackson.databind中的那个(在堆栈跟踪中引用)可以在jackson-databind-2.7.3.jar或jeric-all-2.18中找到.jar:

com/fasterxml/jackson/databind/SerializationConfig.class
./jackson-databind-2.7.3.jar
org/codehaus/jackson/map/SerializationConfig.class
./jackson-mapper-asl-1.9.13.jar
com/fasterxml/jackson/databind/SerializationConfig.class
./jersey-all-2.18.jar

我首先会尝试减少你的依赖关系,这样你就可以依赖 jackson-databind-2.7.3.jar 或 jersey-all-2.18.jar,但不能同时依赖两者。如果您的应用程序可以与其中一个一起使用,我怀疑这将解决您的问题(尽管我承认我可能期望看到Spring的“没有独特的豆子类型......被定义“消息,我没有在你的帖子中注意到它)。

无论如何,如果我是对的,那么你所看到的是类加载在本地环境中发生的工件与 Jenkins 生成的工件中发生的事情和部署在服务器上的情况不同(这里增加了复杂性- 你可能想要仔细检查你的服务器上是否有任何提供的库,并确切地了解你的类加载发生的顺序 - 不好玩, 我知道)。

在查看 Jackson 的 SerializationConfig 类的源代码时,我发现了以下内容,如果两个不同的 jar 文件中的类实际上并不相同,这可能会使事情变得有趣。

private static final long serialVersionUID = 1

希望它有帮助。祝你好运!

编辑1:

设置一对构建版本可能会很有趣,这些构建器使用一些嵌入式服务器(如Tomcat或Jetty)生成所谓的“胖罐”文件。如果您比较本地生产的产品与 Jenkins 上生产的行为,您可能会从中学到一些东西。你看到同样的问题了吗?使用胖 jar 文件,与部署到现有(和预配置的、可更改的)容器中相比,您可以更明确地控制已部署的环境。

编辑2:

您可以做的几件事有助于找出您的环境差异。

mvn dependency:tree

或者,如果你有很多耐心

mvn -X

答案 2

你确定 Jenkins 清理了构建,即它调用“mvn clean install”而不仅仅是“mvn install”吗?一旦我在本地使用“mvn clean install”,异常消失了,应用程序成功启动。

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.7.4</version>
    </dependency>

    <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.7.4</version>
    </dependency>

    <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.7.4</version>
    </dependency>

推荐