jwilner
jwilner

Reputation: 6606

Upgrading Jackson maven dependency issues

I'm trying to upgrade Jackson from 1.9.2 to 2.5.4 in my maven managed Spring web app. It all works just dandy, but blows up in one obscure corner where we have a windows azure integration.

The (I believe) relevant parts of the pom.xml are:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.5.4</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.5.4</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-json-provider</artifactId>
        <version>2.5.4</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.module</groupId>
        <artifactId>jackson-module-jaxb-annotations</artifactId>
        <version>2.5.4</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-joda</artifactId>
        <version>2.5.4</version>
    </dependency>

And:

    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-servicebus</artifactId>
        <version>0.7.0</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-storage</artifactId>
        <version>2.1.0</version>
        <scope>runtime</scope>
    </dependency>

The exception at runtime is:

java.lang.NoClassDefFoundError: org/codehaus/jackson/annotate/JsonUnwrapped
        at org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector.shouldUnwrapProperty(JacksonAnnotationIntrospector.java:153) ~[jackson-mapper-asl-
1.9.2.jar:1.9.2]
        at org.codehaus.jackson.map.deser.BeanDeserializer._resolveUnwrappedProperty(BeanDeserializer.java:515) ~[jackson-mapper-asl-1.9.2.jar:1.9.2]
        at org.codehaus.jackson.map.deser.BeanDeserializer.resolve(BeanDeserializer.java:384) ~[jackson-mapper-asl-1.9.2.jar:1.9.2]
        at org.codehaus.jackson.map.deser.StdDeserializerProvider._resolveDeserializer(StdDeserializerProvider.java:438) ~[jackson-mapper-asl-1.9.2.jar:1.9.2]
        at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCache2(StdDeserializerProvider.java:383) ~[jackson-mapper-asl-1.9.2.jar:1.9.2]
        at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCacheValueDeserializer(StdDeserializerProvider.java:321) ~[jackson-mapper-asl-1.9.2
.jar:1.9.2]
        at org.codehaus.jackson.map.deser.StdDeserializerProvider.findValueDeserializer(StdDeserializerProvider.java:167) ~[jackson-mapper-asl-1.9.2.jar:1.9.2]
        at org.codehaus.jackson.map.deser.StdDeserializerProvider.findTypedValueDeserializer(StdDeserializerProvider.java:188) ~[jackson-mapper-asl-1.9.2.jar:1
.9.2]
        at org.codehaus.jackson.map.ObjectMapper._findRootDeserializer(ObjectMapper.java:2820) ~[jackson-mapper-asl-1.9.2.jar:1.9.2]
        at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2719) ~[jackson-mapper-asl-1.9.2.jar:1.9.2]
        at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1926) ~[jackson-mapper-asl-1.9.2.jar:1.9.2]
        at com.microsoft.windowsazure.services.servicebus.implementation.BrokerPropertiesMapper.fromString(BrokerPropertiesMapper.java:37) ~[azure-servicebus-0
.7.0.jar:na]
        at com.microsoft.windowsazure.services.servicebus.implementation.ServiceBusRestProxy.receiveMessage(ServiceBusRestProxy.java:259) ~[azure-servicebus-0.
7.0.jar:na]
        at com.microsoft.windowsazure.services.servicebus.implementation.ServiceBusRestProxy.receiveQueueMessage(ServiceBusRestProxy.java:216) ~[azure-serviceb
us-0.7.0.jar:na]
        at com.microsoft.windowsazure.services.servicebus.implementation.ServiceBusExceptionProcessor.receiveQueueMessage(ServiceBusExceptionProcessor.java:137
) ~[azure-servicebus-0.7.0.jar:na]

A big part of what I don't understand is why Maven doesn't simply pull in the right dependency for Azure -- it's not technically a dependency convergence issue because the groupId and everything have changed from org.codehaus to com.fasterxml. When I switched the dependency to runtime scope, the error disappeared, but then our IDEs complains that the dependency isn't available, which is prohibitive.

I've tried including the old versions explicitly, and the error doesn't occur.

    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-jaxrs</artifactId>
        <version>1.9.13</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.9.13</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-xc</artifactId>
        <version>1.9.13</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-core-asl</artifactId>
        <version>1.9.13</version>
    </dependency>

I also tried exclusions:

    <!-- Honeywell: AZURE -->
    <!-- Don't let it pull in old jackson -->
    <dependency>
      <groupId>com.microsoft.azure</groupId>
      <artifactId>azure-servicebus</artifactId>
      <version>0.7.0</version>
      <exclusions>
        <exclusion>
          <groupId>org.codehaus.jackson</groupId>
          <artifactId>jackson-jaxrs</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.codehaus.jackson</groupId>
          <artifactId>jackson-mapper-asl</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.codehaus.jackson</groupId>
          <artifactId>jackson-xc</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-storage</artifactId>
        <version>2.1.0</version>
        <exclusions>
          <exclusion>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-jaxrs</artifactId>
          </exclusion>
          <exclusion>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
          </exclusion>
          <exclusion>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-xc</artifactId>
          </exclusion>
        </exclusions>
    </dependency>

Why can't mvn handle this situation? What's the best way to remedy it?

Upvotes: 2

Views: 14888

Answers (3)

Peter Pan
Peter Pan

Reputation: 24128

Per my experience, Azure Service Bus used Jersey-Json which latest version dependents on Jackson 1.9.2 jars. You can see these details here: https://github.com/Azure/azure-sdk-for-java/blob/master/serviceBus/pom.xml and http://mvnrepository.com/artifact/com.sun.jersey/jersey-json/1.19.

Though you need to use Jackson 2.5.4 in your Spring WebApp, it is not conflict with Azure used Jackson version, because they have different full package name. So to manage Java package dependency with maven, you just figure out azure package information, and maven will autoinstall azure dependency packages such as the old version packages of Jackson.

When I tried to reproduce your failure with your first pom.xml in my Eclipse project and run maven install command, Jackson 1.9.2 jars have been installed. I run my program to send & receive message through Azure servicebus queue without any error.

This is the package list of my Eclipse project with maven. enter image description here

Any concerns, please feel free to let me know.

Upvotes: 1

boly38
boly38

Reputation: 1955

Try to keep only fasterxml jackson version

codehaus is an old version of Jackson.

For example in my case I used documentdb and I have exluded jackson (asl) dependency from azure deps (wich rely on old jackson codehaus version).

    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-documentdb</artifactId>
        <version>1.0.1</version>
        <exclusions>
            <!-- old jackson library replaced by jackson data-bind -->
            <exclusion>
                <groupId>org.codehaus.jackson</groupId>
                <artifactId>jackson-mapper-asl</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

Using dependency management view of eclipse (pom.xml) editor could help to check dependencies conflicts and fix it with <exclude>

edit: I complete my answer with an example even if this doesn't fix your issue; maybe this could help similar issues from other Azure/Jackson users. I'm not sure but I think that jar conflicts could cause NoClassDefFound.

Upvotes: 0

manish
manish

Reputation: 20135

If you look at the source code for the class BrokerPropertiesMapper that throws the exception, you will see that it uses com.codehaus version of the Jackson classes. If you check the dependency tree for the Maven module that contains this class, you can see that Jackson 1.9.2 JARs are inherited from the jersey-json dependency.

Since Azure Service Bus has an explicit dependency on Jackson 1.9.2 JARs, you will need 1.9.x JARs on your runtime classpath due to the difference in package structure between 1.9.x and 2.x.

You will also see that the master branch of the Azure SDK project still has the explicit dependency on Jackson 1.9.2. You can file an issue in the Github issue tracker for the project to get this rectified. However, for the time being you are stuck with keeping Jackson 1.9.2 on your runtime classpath. If your own code uses Jackson directly, you should be able to add both 2.x and 1.9.x JARs to your project, with your code using 2.x version of the Jackson classes while third-party libraries using the 1.9.x version.

Upvotes: 2

Related Questions