awslabs / aws-sdk-kotlin

Multiplatform AWS SDK for Kotlin

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Upgrading to 0.29.0-Beta introduces slf4j dependency hell: NoSuchMethodError

mgroth0 opened this issue · comments

Describe the bug

I'm using the sdk in gradle. That is, in a gradle "plugin" that shares a classpath with the Gradle API. Things were fine before, but suddenly after the new update I'm getting a NoSuchMethodError.

Expected behavior

No error

Current behavior

On an sdk method call, I get the following:

java.lang.NoSuchMethodError: 'boolean org.slf4j.Logger.isEnabledForLevel(org.slf4j.event.Level)'
	at aws.smithy.kotlin.runtime.telemetry.logging.slf4j.Slf4JLoggerAdapter.isEnabledFor(Slf4jLoggerProvider.kt:38)
	at aws.smithy.kotlin.runtime.telemetry.logging.CoroutineContextLogExtKt.log(CoroutineContextLogExt.kt:74)
	at aws.smithy.kotlin.runtime.http.operation.OperationHandler.call(SdkOperationExecution.kt:398)
	at aws.smithy.kotlin.runtime.http.operation.OperationHandler.call(SdkOperationExecution.kt:200)
	at aws.smithy.kotlin.runtime.http.operation.SdkHttpOperationKt$execute$$inlined$withSpan$1.invokeSuspend(CoroutineContextTraceExt.kt:126)
	at aws.smithy.kotlin.runtime.http.operation.SdkHttpOperationKt$execute$$inlined$withSpan$1.invoke(CoroutineContextTraceExt.kt)
	at aws.smithy.kotlin.runtime.http.operation.SdkHttpOperationKt$execute$$inlined$withSpan$1.invoke(CoroutineContextTraceExt.kt)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:78)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:167)
	at kotlinx.coroutines.BuildersKt.withContext(Unknown Source)
	at aws.smithy.kotlin.runtime.http.operation.SdkHttpOperationKt.execute(SdkHttpOperation.kt:157)
	at aws.sdk.kotlin.services.s3.DefaultS3Client.getObject(DefaultS3Client.kt:2169)

Steps to Reproduce

Creating a perfect reproducer seems very time consuming since it involves getting all the dependencies and build logic right. But essentially, it might be something like:

  1. Create a library distribution (folder of jars) that uses the SDK with version 0.29.0-Beta
  2. In settings.gradle.kts, load this folder of jars like so:
buildscript {
    dependencies {
        compile(fileTree(jarFolder))
    }
}
  1. During gradle configuration, try to use the SDK.
  2. You might observe the error

Possible Solution

I'm not sure if the reproduction steps above would work, because its a sort of complex environment that I have and something might be missing. But in any case, I was able to figure out a few things while I was trying to debug this.

First of all, I added this to my code immediately before calling the sdk:

kotlin

println("Logger class source = ${org.slf4j.Logger::class.java.protectionDomain.codeSource.location}")

The output of that is:

Logger class source = file:/Users/matthewgroth/.gradle/wrapper/dists/gradle-8.2.1-all/d8pvvlun5bx6sdtwqhf8y9z4b/gradle-8.2.1/lib/slf4j-api-1.7.30.jar

This is interesting. Note the following:

  • aws.smithy.kotlin:logging-slf4j2-jvm:0.23.0 has a runtime dependency on slf4j-api 2.0.6 (see: https://repo1.maven.org/maven2/aws/smithy/kotlin/logging-slf4j2-jvm/0.23.0/logging-slf4j2-jvm-0.23.0.pom)
  • I made absolute sure that an updated slf4j-api jar was included on the class path. slf4j-api-2.0.6 is in fact added as a compile dependency in my settings.gradle.kts right next to the sdk.
  • The method in question isEnabledForLevel is in fact only present in slf4j 2.x.
  • I even tried adding slf4j-nop to the classpath, but this did not help.
  • I'm guessing that gradle loads up the Logger class from its own internal slf4j 1.x jar before I even add the sdk.

At a bare minimum, having a way to disable logging completely to dodge this error in the meantime while a more robuse solution is eventually implemented would be great.

Context

Gradle Version: 8.2.1
Kotlin Version: 1.9.0

I was in sort of desperate need for the new update, because I kept running into #905

The above issue does have a workaround. I have implemented custom retry logic, which mostly works. But even this is failing sometimes. I'm very eager to try the solution that was seemingly implemented in 0.29.0

When I downgrade back to 0.28.0-beta, I dodge the slf4j dependency hell issue, but re-introduce the old java.io.EOFException: \n not found: limit=0 content=… from the above referenced issue.

AWS Kotlin SDK version used

0.29.0-beta

Platform (JVM/JS/Native)

JVM

Operating System and version

Mac

I am testing 0.28.2-beta right now. So far no errors. I will update this if I see any.

Thanks for the issue. Indeed in 0.29.0-beta we took a dependency on SLF4J 2.x whereas previously we were on 1.x.

  1. What are you trying to do/create?
  2. It's not clear what the setup is here: load this folder of jars like so:, how are you managing dependencies?
  3. Are you dependent on a specific SLF4J version or you just happen to use whatever the SDK does and there is a conflict now with gradle?

During gradle configuration, try to use the SDK.

  1. From this comment it would appear as if you are trying to use the SDK from a gradle script (and if I'm reading this right during the configure phase and not while executing a task).

I can provide some suggestions perhaps but it doesn't really look like an issue with the SDK, it's an issue with your classpath + gradle.

@aajtodd Thanks for the response and for the offer to provide some advice.

Sorry my original issue was so messy. I did not even want to try to make a reproducer because my project was so complex. But I did actually just try now, and luckily I was wrong. It was actually very simple and easy to reproduce!

https://github.com/mgroth0/aws-slf4j-dep-hell

There it is. If you clone and try to run any gradle command there, you should hopefully see the error.