javajacksonjava-17objectmapper

java.lang.NoSuchMethodError: 'void com.fasterxml.jackson.core.util.BufferRecycler.releaseToPool()'


I've upgraded Jackson from 2.16.1 to 2.18.2 in my build.gradle:

plugins {
    id 'java'
    id 'jacoco'
    id 'com.github.johnrengelman.shadow' version '8.1.1'
    id "org.sonarqube" version "${sonarqubeVersion}"
}

ext {
    awsLambdaJavaCoreVersion = '1.2.3'
    awsLambdaEventsVersion = '3.12.0'
    jacksonDatabindVersion = '2.18.2'
    awsLambdaTransformerVersion = '3.1.0'
    guavaVersion = '33.2.1-jre'
    javaJwtVersion = '4.4.0'
}

dependencies {
    implementation project(":fdx-6")
    implementation (project(":common")) {
        exclude group: 'org.springframework.boot'
        exclude group: 'software.amazon.awssdk', module: 'url-connection-client'
    }
    implementation "software.amazon.awssdk:sqs"
    implementation "software.amazon.awssdk:lambda"
    implementation "org.springframework:spring-web"
    implementation "org.springframework.security:spring-security-core:6.2.5"
    implementation "com.amazonaws:aws-lambda-java-core:$awsLambdaJavaCoreVersion"
    implementation "com.amazonaws:aws-lambda-java-events:$awsLambdaEventsVersion"
    implementation "com.amazonaws:aws-lambda-java-events-sdk-transformer:$awsLambdaTransformerVersion"
    implementation "com.amazonaws:aws-lambda-java-log4j2:1.6.0"
    implementation 'com.amazonaws:dynamodb-lock-client:1.2.0'
    implementation 'software.amazon.awssdk:dynamodb-enhanced'
    implementation "com.fasterxml.jackson.core:jackson-core:$jacksonDatabindVersion"
        implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonDatabindVersion"
        implementation "com.fasterxml.jackson.module:jackson-module-afterburner:$jacksonDatabindVersion"
    implementation "com.nimbusds:nimbus-jose-jwt:${nimbusJoseVersion}"
    implementation "io.netty:netty-codec-http:${nettyHttpVersion}"
    implementation "com.google.guava:guava:$guavaVersion"
    implementation "com.auth0:java-jwt:$javaJwtVersion"
    implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jacksonDatabindVersion"
    implementation "com.nimbusds:nimbus-jose-jwt:${nimbusJoseVersion}"
    //opentelemetry
    compileOnly "io.opentelemetry:opentelemetry-api"
    compileOnly "io.opentelemetry.instrumentation:opentelemetry-aws-lambda-events-2.2:${opentelemetryInstrumentationVersionAlpha}"
    compileOnly "io.opentelemetry.instrumentation:opentelemetry-aws-sdk-2.2:${opentelemetryInstrumentationVersionAlpha}"
    implementation "io.opentelemetry.instrumentation:opentelemetry-java-http-client:${opentelemetryInstrumentationVersionAlpha}"
    implementation "com.amazonaws:aws-lambda-java-log4j2:1.6.0"
    implementation 'org.apache.logging.log4j:log4j-layout-template-json:2.17.1'

    compileOnly "org.projectlombok:lombok"
    implementation "org.mapstruct:mapstruct:${mapStructVersion}"
    annotationProcessor "org.projectlombok:lombok"
    annotationProcessor "org.mapstruct:mapstruct-processor:${mapStructVersion}"

    testImplementation 'com.amazonaws:aws-lambda-java-tests:1.1.1'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation "org.mapstruct:mapstruct:${mapStructVersion}"
    testImplementation 'uk.org.webcompere:system-stubs-jupiter:2.1.6'
    testImplementation "io.opentelemetry.instrumentation:opentelemetry-aws-sdk-2.2:${opentelemetryInstrumentationVersionAlpha}"
}

Now this Java code

@UtilityClass
public class ObjectMapperUtil {

    public static final TypeReference<HashMap<String, Object>> STRING_OBJ_TYPE_REF = new TypeReference<>() {
    };
    public static final TypeReference<HashMap<String, String>> STRING_STRING_TYPE_REF = new TypeReference<>() {
    };

    private static final ObjectMapper objectMapper = JsonMapper.builder()
            .addModule(new JavaTimeModule())
            .addModule(new AfterburnerModule())
            .build();

    public static String toJsonString(Object obj) {
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Error converting object to JSON", e);
        }
    }
}

throws java.lang.NoSuchMethodError: 'void com.fasterxml.jackson.core.util.BufferRecycler.releaseToPool()':

java.lang.NoSuchMethodError: 'void com.fasterxml.jackson.core.util.BufferRecycler.releaseToPool()'

    at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:4059)
    at com.c.o.common.utils.ObjectMapperUtil.toJsonString(ObjectMapperUtil.java:29)

Any ideas how could I fix this without dependency downgrade?


Solution

  • The culprit appeared to be com.auth0:java-jwt:4.4.0 for it is transitively dependent on com.fasterxml.jackson.core:jackson-databind:2.14.2 and com.fasterxml.jackson:jackson-bom:2.15.4. Here's the output of gradle dependencies:

    +--- com.auth0:java-jwt:4.4.0
    |    \--- com.fasterxml.jackson.core:jackson-databind:2.14.2 -> 2.18.2
    |         +--- com.fasterxml.jackson.core:jackson-annotations:2.18.2 -> 2.15.4
    |         |    \--- com.fasterxml.jackson:jackson-bom:2.15.4 -> 2.18.2
    |         |         +--- com.fasterxml.jackson.core:jackson-annotations:2.18.2 -> 2.15.4 (c)
    |         |         +--- com.fasterxml.jackson.core:jackson-core:2.18.2 -> 2.15.4 (c)
    |         |         +--- com.fasterxml.jackson.core:jackson-databind:2.18.2 (c)
    |         |         +--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2 (c)
    |         |         \--- com.fasterxml.jackson.module:jackson-module-afterburner:2.18.2 (c)
    |         +--- com.fasterxml.jackson.core:jackson-core:2.18.2 -> 2.15.4
    |         |    \--- com.fasterxml.jackson:jackson-bom:2.15.4 -> 2.18.2 (*)
    |         \--- com.fasterxml.jackson:jackson-bom:2.18.2 (*)
    

    There void com.fasterxml.jackson.core.util.BufferRecycler indeed does not declare releaseToPool() method.

    To fix this I've enforced use of 2.18.2 for all Jackson-related dependencies by adding the following config into build.gradle:

    configurations {
        all {
            resolutionStrategy.eachDependency { details ->
                if (details.requested.group.startsWith("com.fasterxml.jackson")) {
                    details.useVersion("$jacksonDatabindVersion")
                }
            }
        }
    }
    

    Here is the dependency tree after:

    +--- com.auth0:java-jwt:4.4.0
    |    \--- com.fasterxml.jackson.core:jackson-databind:2.14.2 -> 2.18.2
    |         +--- com.fasterxml.jackson.core:jackson-annotations:2.18.2
    |         |    \--- com.fasterxml.jackson:jackson-bom:2.18.2
    |         |         +--- com.fasterxml.jackson.core:jackson-annotations:2.18.2 (c)
    |         |         +--- com.fasterxml.jackson.core:jackson-core:2.18.2 (c)
    |         |         +--- com.fasterxml.jackson.core:jackson-databind:2.18.2 (c)
    |         |         +--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2 (c)
    |         |         \--- com.fasterxml.jackson.module:jackson-module-afterburner:2.18.2 (c)
    |         +--- com.fasterxml.jackson.core:jackson-core:2.18.2
    |         |    \--- com.fasterxml.jackson:jackson-bom:2.18.2 (*)
    |         \--- com.fasterxml.jackson:jackson-bom:2.18.2 (*)
    

    With the newer version method void com.fasterxml.jackson.core.util.BufferRecycler.releaseToPool() is resolved.