Azure / azure-sdk-for-java

This repository is for active development of the Azure SDK for Java. For consumers of the SDK we recommend visiting our public developer docs at https://docs.microsoft.com/java/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-java.
MIT License
2.35k stars 1.99k forks source link

[BUG] 7.16.0 LinkagerError #40066

Closed MBurchard closed 6 months ago

MBurchard commented 6 months ago

Describe the bug After upgrade from Version 7.15.2 (wich worked fine) to 7.16.0 our Azure Service Bus Code does not work any more. In the Release Notes there was this written:

https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/servicebus/azure-messaging-servicebus/CHANGELOG.md#features-added-1

My understanding: the MS library does not use Jackson XML any more. But the stack trace looks, like they do...

Exception or Stack Trace

java.lang.ExceptionInInitializerError: Exception java.lang.LinkageError: Package versions: jackson-core=2.17.1, jackson-databind=2.17.1, jackson-dataformat-xml=unknown, jackson-datatype-jsr310=2.17.1, azure-core=1.47.0, Troubleshooting version conflicts: https://aka.ms/azsdk/java/dependency/troubleshoot [in thread "http-nio-8080-exec-7"]
    at com.azure.core.implementation.jackson.ObjectMapperShim.createXmlMapper(ObjectMapperShim.java:84) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.util.serializer.JacksonAdapter$GlobalXmlMapper.<clinit>(JacksonAdapter.java:60) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.util.serializer.JacksonAdapter.getXmlMapper(JacksonAdapter.java:462) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.util.serializer.JacksonAdapter.lambda$deserialize$8(JacksonAdapter.java:320) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.util.serializer.JacksonAdapter.useAccessHelper(JacksonAdapter.java:483) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.util.serializer.JacksonAdapter.deserialize(JacksonAdapter.java:315) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.messaging.servicebus.administration.implementation.ServiceBusManagementSerializer.deserialize(ServiceBusManagementSerializer.java:115) ~[azure-messaging-servicebus-7.16.0.jar:7.16.0]
    at com.azure.messaging.servicebus.administration.implementation.ServiceBusManagementSerializer.deserialize(ServiceBusManagementSerializer.java:128) ~[azure-messaging-servicebus-7.16.0.jar:7.16.0]
    at com.azure.core.util.serializer.SerializerAdapter.deserialize(SerializerAdapter.java:126) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.implementation.serializer.HttpResponseBodyDecoder.deserialize(HttpResponseBodyDecoder.java:176) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.implementation.serializer.HttpResponseBodyDecoder.deserializeBody(HttpResponseBodyDecoder.java:150) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.implementation.serializer.HttpResponseBodyDecoder.decodeByteArray(HttpResponseBodyDecoder.java:67) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.implementation.serializer.HttpResponseDecoder$HttpDecodedResponse.getDecodedBody(HttpResponseDecoder.java:93) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.implementation.http.rest.SyncRestProxy.ensureExpectedStatus(SyncRestProxy.java:127) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.implementation.http.rest.SyncRestProxy.handleRestReturnType(SyncRestProxy.java:206) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.implementation.http.rest.SyncRestProxy.invoke(SyncRestProxy.java:82) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.implementation.http.rest.RestProxyBase.invoke(RestProxyBase.java:128) ~[azure-core-1.47.0.jar:1.47.0]
    at com.azure.core.http.rest.RestProxy.invoke(RestProxy.java:97) ~[azure-core-1.47.0.jar:1.47.0]
    at jdk.proxy2/jdk.proxy2.$Proxy225.getSync(Unknown Source) ~[na:na]
    at com.azure.messaging.servicebus.administration.implementation.SubscriptionsImpl.getWithResponse(SubscriptionsImpl.java:213) ~[azure-messaging-servicebus-7.16.0.jar:7.16.0]
    at com.azure.messaging.servicebus.administration.ServiceBusAdministrationClient.lambda$getSubscriptionInternal$12(ServiceBusAdministrationClient.java:946) ~[azure-messaging-servicebus-7.16.0.jar:7.16.0]
    at com.azure.messaging.servicebus.administration.ServiceBusAdministrationClient.executeAndThrowException(ServiceBusAdministrationClient.java:1762) ~[azure-messaging-servicebus-7.16.0.jar:7.16.0]
    at com.azure.messaging.servicebus.administration.ServiceBusAdministrationClient.getSubscriptionInternal(ServiceBusAdministrationClient.java:944) ~[azure-messaging-servicebus-7.16.0.jar:7.16.0]
    at com.azure.messaging.servicebus.administration.ServiceBusAdministrationClient.lambda$getSubscriptionExistsWithResponse$13(ServiceBusAdministrationClient.java:983) ~[azure-messaging-servicebus-7.16.0.jar:7.16.0]
    at com.azure.messaging.servicebus.administration.ServiceBusAdministrationClient.getEntityExistsWithResponse(ServiceBusAdministrationClient.java:1162) ~[azure-messaging-servicebus-7.16.0.jar:7.16.0]
    at com.azure.messaging.servicebus.administration.ServiceBusAdministrationClient.getSubscriptionExistsWithResponse(ServiceBusAdministrationClient.java:983) ~[azure-messaging-servicebus-7.16.0.jar:7.16.0]
    at com.azure.messaging.servicebus.administration.ServiceBusAdministrationClient.getSubscriptionExists(ServiceBusAdministrationClient.java:964) ~[azure-messaging-servicebus-7.16.0.jar:7.16.0]
    at com.uniper.comstar.servicebus.SubscriptionService.register(SubscriptionService.kt:111) ~[main/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]

To Reproduce I can not provide the whole project to reproduce the error. It occurs when calling getSubscriptionExists

Code Snippet

if (sbAdminClient.getSubscriptionExists(clientConnectionConfig.topic, subscription)) {
          log.debug { "Subscription '${subscription}' on topic '${clientConnectionConfig.topic}' already available" }
          return SubscriptionResult(
            clientConnectionConfig.connectionString!!,
            subscription,
            clientConnectionConfig.topic!!,
            type
          )
        }

Expected behavior It should work like in 7.15.2, because only the Version of the MS library has been increased, nothing else changed.

Setup (please complete the following information):

Information Checklist Kindly make sure that you have added all the following information above and checkoff the required fields otherwise we will treat the issuer as an incomplete report

github-actions[bot] commented 6 months ago

@anuchandy @conniey @lmolkova

github-actions[bot] commented 6 months ago

Thank you for your feedback. Tagging and routing to the team member best able to assist.

anuchandy commented 6 months ago

Hello @MBurchard, you're correct, library has switched from Jackson to azure-xml since 7.16.0, but this also needs the azure-core:1.48.0 (as specified in azure-messaging-servicebus:7.16.0 POM file).

It is possible that applications have other dependencies that override the needed azure-core:1.48.0, leading class-loader to resolve an older version instead. You can verify such a dependency conflict using "maven dependency:tree". In this case, you want to manually update the versions of other dependencies that cause this conflict (Between Azure SDK also offer BOM).

alzimmermsft commented 6 months ago

Hi @MBurchard, I was able to verify what @anuchandy mentioned, where aligning the azure-core version to match what azure-messaging-servicebus 7.16.0 released using (1.48.0) resolves the LinkageError being seen.

I'm also "+1"'ing Anu's recommendation to use azure-sdk-bom as a dependency manager to ensure version compatibility between Azure SDKs.

github-actions[bot] commented 6 months ago

Hi @MBurchard. Thank you for opening this issue and giving us the opportunity to assist. We believe that this has been addressed. If you feel that further discussion is needed, please add a comment with the text "/unresolve" to remove the "issue-addressed" label and continue the conversation.

MBurchard commented 6 months ago

@anuchandy Thank you for your answer.

I'm using the following Gradle configuration.

dependencyManagement {
  imports {
    mavenBom("com.azure.spring:spring-cloud-azure-dependencies:5.11.0")
  }
}

dependencies {
  implementation("com.auth0:java-jwt:4.4.0")
  implementation("com.azure:azure-messaging-servicebus:7.15.2") // or 7.16.0 which has this LinkagerError
  implementation("com.azure.spring:spring-cloud-azure-starter-servicebus-jms")
  implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
  implementation("com.github.ben-manes.caffeine:caffeine")
  implementation("com.microsoft.graph:microsoft-graph:6.8.0")
  implementation("io.hypersistence:hypersistence-utils-hibernate-63:3.7.5")
  implementation("io.github.microutils:kotlin-logging-jvm:3.0.5")
  implementation("net.javacrumbs.shedlock:shedlock-provider-jdbc-template:5.13.0")
  implementation("net.javacrumbs.shedlock:shedlock-spring:5.13.0")
  implementation("org.apache.maven:maven-artifact:3.9.6")
  implementation("org.apache.commons:commons-lang3:3.14.0")
  implementation("org.apache.commons:commons-text:1.12.0")
  implementation("org.jetbrains.kotlin:kotlin-reflect")
  implementation("org.springframework.boot:spring-boot-starter-actuator")
  implementation("org.springframework.boot:spring-boot-starter-cache")
  implementation("org.springframework.boot:spring-boot-starter-data-jpa")
  implementation("org.springframework.boot:spring-boot-starter-data-redis")
  implementation("org.springframework.boot:spring-boot-starter-mail")
  implementation("org.springframework.boot:spring-boot-starter-mustache")
  implementation("org.springframework.boot:spring-boot-starter-security")
  implementation("org.springframework.boot:spring-boot-starter-validation")
  implementation("org.springframework.boot:spring-boot-starter-web")
  implementation("org.springframework.security:spring-security-oauth2-jose")

  developmentOnly("org.springframework.boot:spring-boot-devtools")

  runtimeOnly("com.microsoft.sqlserver:mssql-jdbc")
  runtimeOnly("org.liquibase:liquibase-core")

  testImplementation("com.ninja-squad:springmockk:$springMockKVersion")
  testImplementation("org.springframework.boot:spring-boot-starter-test")
  testImplementation("org.springframework.security:spring-security-test")
  testImplementation("org.apache.commons:commons-csv:1.11.0")

  testRuntimeOnly("com.h2database:h2")
}

All versions that are not explicitly specified are resolved by Spring Boot and are definitely the latest versions. Changing to com.azure:azure-messaging-servicebus:7.16.0 breaks the project.

Where, why and how do I add the azure-core version 1.48.0 which I seem to never have needed before? Why is the "automatic" resolution of dependencies suddenly broken? /unresolve

alzimmermsft commented 6 months ago

Hi @MBurchard, as part of the release of azure-messaging-servicebus 7.16.0 it took dependencies on new features provided by azure-core 1.48.0 to support the removal of Jackson Dataformat XML.

As for what is causing azure-core 1.47.0 to be resolved when azure-messaging-servicebus 7.16.0 is being used, which references azure-core 1.48.0 explicitly, it's mavenBom("com.azure.spring:spring-cloud-azure-dependencies:5.11.0") as it is using azure-core 1.47.0 as the resolving version. If azure-messaging-servicebus wasn't explicitly defined in your Gradle configuration it would resolve to 7.15.2 as that is the version the Spring Cloud Azure Dependencies BOM is using as well.

Until the Azure Spring BOM has another release I'd recommend defining azure-core in your Gradle configuration explicitly for now.

dependencies {
  implementation("com.auth0:java-jwt:4.4.0")
  implementation("com.azure:azure-core:1.48.0")
  implementation("com.azure:azure-messaging-servicebus:7.16.0")
  ...
github-actions[bot] commented 6 months ago

Hi @MBurchard. Thank you for opening this issue and giving us the opportunity to assist. To help our team better understand your issue and the details of your scenario please provide a response to the question asked above or the information requested above. This will help us more accurately address your issue.

MBurchard commented 6 months ago

Hi @MBurchard, as part of the release of azure-messaging-servicebus 7.16.0 it took dependencies on new features provided by azure-core 1.48.0 to support the removal of Jackson Dataformat XML.

As for what is causing azure-core 1.47.0 to be resolved when azure-messaging-servicebus 7.16.0 is being used, which references azure-core 1.48.0 explicitly, it's mavenBom("com.azure.spring:spring-cloud-azure-dependencies:5.11.0") as it is using azure-core 1.47.0 as the resolving version. If azure-messaging-servicebus wasn't explicitly defined in your Gradle configuration it would resolve to 7.15.2 as that is the version the Spring Cloud Azure Dependencies BOM is using as well.

Until the Azure Spring BOM has another release I'd recommend defining azure-core in your Gradle configuration explicitly for now.

dependencies {
  implementation("com.auth0:java-jwt:4.4.0")
  implementation("com.azure:azure-core:1.48.0")
  implementation("com.azure:azure-messaging-servicebus:7.16.0")
  ...

Ah interesting, thanks for the hint that I can omit the version at 'com.azure:azure-messaging-servicebus'. I'm waiting and not using 7.16.0, but waiting for the next release of 'com.azure.spring:spring-cloud-azure-dependencies'