Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

While we enforcing the OkHttp Library in our Android app Location credential failing #1173

Closed
1 task
drayan85 opened this issue Oct 31, 2024 · 15 comments
Closed
1 task
Labels
question Further information is requested

Comments

@drayan85
Copy link

Describe the bug

Currently we are using the aws.sdk.kotlin:location to 1.3.62 and working as expected if are enforcing the OkHttp library

Regression Issue

  • Select this option if this issue appears to be a regression.

Expected behavior

It supposed work with OKHttp4Engine

Current behavior

  java.lang.NoClassDefFoundError: Failed resolution of: Lokhttp3/coroutines/ExecuteAsyncKt;
  	at aws.smithy.kotlin.runtime.http.engine.okhttp.OkHttpEngine.roundTrip(OkHttpEngine.kt:56)
  	at aws.smithy.kotlin.runtime.http.engine.internal.ManagedHttpClientEngine.roundTrip(Unknown Source:2)
  	at aws.smithy.kotlin.runtime.http.SdkHttpClient$executeWithCallContext$2.invokeSuspend(SdkHttpClient.kt:44)
  	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
  	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:101)
  	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:589)
  	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:832)
  	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:720)
  	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:707)
  Caused by: java.lang.ClassNotFoundException: Didn't find class "okhttp3.coroutines.ExecuteAsyncKt" on path: DexPathList[[dex file "/data/data/com.aws.testing/code_cache/.overlay/base.apk/classes13.dex", zip file "/data/app/~~pd18IQU0o1qsVUQG46H77Q==/com.aws.testing-jM1Bxk7yGtOSle0L-v5mlg==/base.apk"],nativeLibraryDirectories=[/data/app/~~pd18IQU0o1qsVUQG46H77Q==/com.aws.testing-jM1Bxk7yGtOSle0L-v5mlg==/lib/arm64, /data/app/~~pd18IQU0o1qsVUQG46H77Q==/com.aws.testing-jM1Bxk7yGtOSle0L-v5mlg==/base.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64]]
  	at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
  	at java.lang.ClassLoader.loadClass(ClassLoader.java:637)
  	at java.lang.ClassLoader.loadClass(ClassLoader.java:573)
  	... 9 more

Steps to Reproduce

dependencies {
    implementation ("software.amazon.location:auth:1.3.62")
    implementation("aws.sdk.kotlin:location:0.2.5")
    implementation("aws.smithy.kotlin:http-client-engine-okhttp4:1.3.12") 
}

configurations.all {
    resolutionStrategy {
        force("com.squareup.okhttp3:okhttp:4.12.0") 
    }
    exclude(group = "com.squareup.okhttp3", module = "okhttp-coroutines") 
}

Code implementation

  private var locationCredentialsProvider: LocationCredentialsProvider? = null
  private var locationClient: LocationClient? = null

  suspend fun getLocationClient(): LocationClient {
    return runCatching {
      if (locationClient == null) {
        val poolId = configRepository.getRemoteConfigValue("***************************")
        if (poolId != null) {
          locationCredentialsProvider = AuthHelper(context).authenticateWithCognitoIdentityPool(poolId)
        }
        locationClient = locationCredentialsProvider?.getLocationClient() ?: error("CLIENT Location Client Retrieval failed")
        locationClient!!.withConfig {
          httpClient = OkHttp4Engine()
        }
      }
      locationClient!!
    }.getOrElse { e ->
      e.printStackTrace()
      error("COGNITO authentication failed")
    }
  }

Possible Solution

By changing the gradle config as follows to use the okhttp-coroutine:5.0.0-alpha.14 :

configurations.configureEach {
    resolutionStrategy {
        force("com.squareup.okhttp3:okhttp:4.12.0") 
    }
}

I just remove the exclude group: "com.squareup.okhttp3", module: "okhttp-coroutines"

Android app working as expected and my Dependency Graph looks like:

+--- com.squareup.okhttp3:okhttp-coroutines:{strictly 5.0.0-alpha.14} -> 5.0.0-alpha.14 (c)
|         |         +--- aws.smithy.kotlin:http-client-engine-default:1.3.17
|         |         |    \--- aws.smithy.kotlin:http-client-engine-default-jvm:1.3.17
|         |         |         +--- aws.smithy.kotlin:http-client:1.3.17 (*)
|         |         |         +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.21 (*)
|         |         |         +--- aws.smithy.kotlin:http-client-engine-okhttp:1.3.17
|         |         |         |    \--- aws.smithy.kotlin:http-client-engine-okhttp-jvm:1.3.17
|         |         |         |         +--- aws.smithy.kotlin:http-client:1.3.17 (*)
|         |         |         |         +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.21 (*)
|         |         |         |         +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0 (*)
|         |         |         |         +--- aws.smithy.kotlin:runtime-core:1.3.17 (*)
|         |         |         |         +--- aws.smithy.kotlin:telemetry-defaults:1.3.17
|         |         |         |         |    \--- aws.smithy.kotlin:telemetry-defaults-jvm:1.3.17
|         |         |         |         |         +--- aws.smithy.kotlin:telemetry-api:1.3.17 (*)
|         |         |         |         |         +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.21 (*)
|         |         |         |         |         +--- aws.smithy.kotlin:logging-slf4j2:1.3.17
|         |         |         |         |         |    \--- aws.smithy.kotlin:logging-slf4j2-jvm:1.3.17
|         |         |         |         |         |         +--- aws.smithy.kotlin:telemetry-api:1.3.17 (*)
|         |         |         |         |         |         +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.21 (*)
|         |         |         |         |         |         +--- org.slf4j:slf4j-api:2.0.16
|         |         |         |         |         |         \--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0 (*)
|         |         |         |         |         \--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0 (*)
|         |         |         |         +--- com.squareup.okhttp3:okhttp:5.0.0-alpha.14 -> 4.12.0 (*)
|         |         |         |         \--- com.squareup.okhttp3:okhttp-coroutines:5.0.0-alpha.14
|         |         |         |              +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0 -> 1.9.0 (*)
|         |         |         |              +--- com.squareup.okhttp3:okhttp:5.0.0-alpha.14 -> 4.12.0 (*)
|         |         |         |              +--- com.squareup.okio:okio:3.9.0 -> 3.9.1 (*)
|         |         |         |              \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.23 -> 2.0.21 (*)
|         |         |         +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0 (*)
|         |         |         \--- aws.smithy.kotlin:runtime-core:1.3.17 (*)

Context

I attempted to use okhttp-coroutine from version 5.0.0-alpha.14 while enforcing Okhttp version 4.12.0, and it worked successfully. However, I'm uncertain of any potential consequences.

Smithy-Kotlin version

aws.sdk.kotlin:location :1.2.62

Platform (JVM/JS/Native)

JVM (Kotlin) JDK 17

Operating system and version

Android 13

@drayan85 drayan85 added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Oct 31, 2024
@lauzadis lauzadis added question Further information is requested and removed bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Oct 31, 2024
@lauzadis
Copy link
Contributor

Related issue: awslabs/aws-sdk-kotlin#1411

Are you able to configure your application to use the standard OkHttp engine (not OkHttp4Engine)? If not, I don't see an immediate problem with using OkHttp4Engine and using okhttp-coroutines v5.0.0-alpha.14.

@drayan85
Copy link
Author

drayan85 commented Oct 31, 2024

Yes, we are able configure the application to use the standard OkHttp Engine but Our daily integration tests are failing due to a transient dependency on the OkHttp library (v5.0.0-alpha.14) required by the AWS Library.

Our integration test suite is essential for detecting potential issues introduced by new code changes. Previously, we were using the Google Places API, but since migrating to the AWS Location API, we’ve encountered this issue.

@lauzadis
Copy link
Contributor

lauzadis commented Nov 1, 2024

Can you clarify, are you able to successfully use OkHttp v5.0.0-alpha.14 in the AWS SDK for Kotlin or not?

Either way, if OkHttp4Engine is working for you, I see no issues with the usage of okhttp-coroutines you described.

@drayan85
Copy link
Author

drayan85 commented Nov 1, 2024

Can you clarify, are you able to successfully use OkHttp v5.0.0-alpha.14 in the AWS SDK for Kotlin or not?

It is functioning correctly; however, the CI/CD pipeline is failing due to a version mismatch with the OKHttp MockWebServer, which is causing delays in releasing the production version.

Additionally, our policy does not permit any libraries in production to use unstable versions, such as OkHttp Alpha.

@lauzadis
Copy link
Contributor

lauzadis commented Nov 1, 2024

Additionally, our policy does not permit any libraries in production to use unstable versions, such as OkHttp Alpha.

This is exactly the reason we've created OkHttp4Engine. It sounds like you're able to successfully configure your application to use that engine and resolve all version compatibility issues.

I can't help you fix your CI/CD problems, if there is an SDK-specific issue please let me know, otherwise this issue will be closed soon.

@drayan85
Copy link
Author

drayan85 commented Nov 4, 2024

This is exactly the reason we've created OkHttp4Engine. It sounds like you're able to successfully configure your application to use that engine and resolve all version compatibility issues.

What I am referring is when enforce the OkHttp4Engine with the following configuration is still crashing:

configurations.all {
    resolutionStrategy {
        force("com.squareup.okhttp3:okhttp:4.12.0") 
    }
    exclude(group = "com.squareup.okhttp3", module = "okhttp-coroutines") 
}
  java.lang.NoClassDefFoundError: Failed resolution of: Lokhttp3/coroutines/ExecuteAsyncKt;
  	at aws.smithy.kotlin.runtime.http.engine.okhttp.OkHttpEngine.roundTrip(OkHttpEngine.kt:56)
  	at aws.smithy.kotlin.runtime.http.engine.internal.ManagedHttpClientEngine.roundTrip(Unknown Source:2)
  	at aws.smithy.kotlin.runtime.http.SdkHttpClient$executeWithCallContext$2.invokeSuspend(SdkHttpClient.kt:44)
  	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
  	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:101)
  	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:589)
  	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:832)
  	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:720)
  	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:707)
  Caused by: java.lang.ClassNotFoundException: Didn't find class "okhttp3.coroutines.ExecuteAsyncKt" on path: DexPathList[[dex file "/data/data/com.aws.testing/code_cache/.overlay/base.apk/classes13.dex", zip file "/data/app/~~pd18IQU0o1qsVUQG46H77Q==/com.aws.testing-jM1Bxk7yGtOSle0L-v5mlg==/base.apk"],nativeLibraryDirectories=[/data/app/~~pd18IQU0o1qsVUQG46H77Q==/com.aws.testing-jM1Bxk7yGtOSle0L-v5mlg==/lib/arm64, /data/app/~~pd18IQU0o1qsVUQG46H77Q==/com.aws.testing-jM1Bxk7yGtOSle0L-v5mlg==/base.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64]]
  	at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
  	at java.lang.ClassLoader.loadClass(ClassLoader.java:637)
  	at java.lang.ClassLoader.loadClass(ClassLoader.java:573)
  	... 9 more

Because it is expecting the okhttp-coroutines which is only introduce in the OkHttp v5.0.0-alpha-x

@lauzadis
Copy link
Contributor

lauzadis commented Nov 5, 2024

Can you please provide a complete minimal reproduction of your issue? The exception you're seeing implies that the OkHttp4Engine is not configured (because OkHttpEngine is invoked).

@drayan85
Copy link
Author

drayan85 commented Nov 7, 2024

import android.content.Context
import aws.sdk.kotlin.services.location.LocationClient
import aws.sdk.kotlin.services.location.withConfig
import aws.smithy.kotlin.runtime.http.engine.okhttp4.OkHttp4Engine
import com.jora.android.config.domain.RemoteConfiguration
import dagger.hilt.android.qualifiers.ApplicationContext
import software.amazon.location.auth.AuthHelper
import software.amazon.location.auth.LocationCredentialsProvider
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class AwsLocationProvider @Inject constructor(
  @ApplicationContext private val context: Context
) {
  private var locationCredentialsProvider: LocationCredentialsProvider? = null
  private var locationClient: LocationClient? = null

  suspend fun getLocationClient(): LocationClient {
    return runCatching {
      if (locationClient == null) {
        if (poolId != null) {
          locationCredentialsProvider = AuthHelper(context).authenticateWithCognitoIdentityPool("COGNITO_POOL_ID)
        }
        locationClient = locationCredentialsProvider?.getLocationClient() ?: error("AWS:CLIENT Location Client Retrieval failed")
        locationClient!!.withConfig {
          httpClient = OkHttp4Engine()
        }
      }
      locationClient!!
    }.getOrElse { e ->
      e.printStackTrace() // to debug the exception thrown by AWS SDK
      error("AWS:COGNITO authentication failed")
    }
  }
}

@drayan85
Copy link
Author

drayan85 commented Nov 7, 2024

I am just wondering, Given that the okhttp-coroutines module introduces OkHttp v5.0.0-alpha-x:

When we do the configuration removing okhttp-coroutines module and enforcing OkHttp4Engine.

Could you please confirm AWS SDK will work without okhttp-coroutines module?

Seems like it is not working without the okhttp-coroutines module.

Screenshot 2024-11-07 at 3 48 08 PM

@lauzadis
Copy link
Contributor

lauzadis commented Nov 7, 2024

That is not a complete reproduction, it's missing a build.gradle.kts script. Can you please provide a minimal reproduction containing that file? A GitHub repository would work. We're unable to debug your dependency problems if you just send a Kotlin file.

@drayan85
Copy link
Author

@lauzadis ,
Here is the Sample Repository which you can use to reproduce the error while Enforcing the OkHttp4Engine

https://github.com/drayan85/AWS-Location-Demo

@lauzadis
Copy link
Contributor

Hello, I was able to reproduce the issue you're having. The root cause is that you're using the software.amazon.location:auth project which creates its own Kotlin SDK clients that are not configured to use the OkHttp4Engine. They are using the default engine which relies on OkHttp5.

I'll reach out to the team which owns that project to see if they can introduce some configuration options so you can use OkHttp4. As a faster workaround I would recommend performing the Cognito authentication yourself with the OkHttp4-configured Kotlin SDK client rather than using this dependency.

@cgalvan
Copy link

cgalvan commented Nov 20, 2024

Hello, I believe I can help. We actually made a change recently that modifies the API of the location authentication SDK to to return the client configuration instead of a client, so if you update to use the latest version 1.1.0 you'll be able to create your own location client and then just use our authentication SDK to provide the proper cognito configuration for the client.

So your location authentication dependency would change to:

implementation("software.amazon.location:auth:1.1.0")

And your code implementation would change to:

private var locationClient: LocationClient? = null

suspend fun getLocationClient(): LocationClient {
  return runCatching {
    if (locationClient == null) {
      val poolId = configRepository.getRemoteConfigValue("***************************")
      val authHelper = AuthHelper.withCognitoIdentityPool(poolId, context)

      locationClient = LocationClient(authHelper?.getLocationClientConfig()) 

      locationClient!!.withConfig {
        httpClient = OkHttp4Engine()
      }
    }
    locationClient!!
  }.getOrElse { e ->
    e.printStackTrace()
    error("COGNITO authentication failed")
  }
}

Please let me know if you run into any issues with this.

@drayan85
Copy link
Author

@cgalvan ,
I have tried as you suggested above and still I am getting error (https://github.com/drayan85/AWS-Location-Demo).
Please change the values for AWS_COGNITO_POOL_ID & AWS_PLACE_INDEX

If you want to reproduce by yourself.

Process: com.aws.demo, PID: 18654
java.lang.NoClassDefFoundError: Failed resolution of: Lokhttp3/coroutines/ExecuteAsyncKt;
	at aws.smithy.kotlin.runtime.http.engine.okhttp.OkHttpEngine.roundTrip(OkHttpEngine.kt:56)
	at aws.smithy.kotlin.runtime.http.engine.internal.ManagedHttpClientEngine.roundTrip(Unknown Source:2)
	at aws.smithy.kotlin.runtime.http.SdkHttpClient$executeWithCallContext$2.invokeSuspend(SdkHttpClient.kt:44)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:101)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:589)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:832)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:720)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:707)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@d5b34a2, Dispatchers.Main.immediate]
Caused by: java.lang.ClassNotFoundException: Didn't find class "okhttp3.coroutines.ExecuteAsyncKt" on path: DexPathList[[dex file "/data/data/com.aws.demo/code_cache/.overlay/base.apk/classes3.dex", dex file "/data/data/com.aws.demo/code_cache/.overlay/base.apk/classes5.dex", zip file "/data/app/~~lOQBgcnKMDcsrlS4c8qxBg==/com.aws.demo-Rr7zKExyvJ5wJD0SAGj7Ug==/base.apk"],nativeLibraryDirectories=[/data/app/~~lOQBgcnKMDcsrlS4c8qxBg==/com.aws.demo-Rr7zKExyvJ5wJD0SAGj7Ug==/lib/arm64, /system/lib64, /system_ext/lib64]]
	at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:637)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:573)

@lauzadis
Copy link
Contributor

We'll be closing this issue for now, let's track resolution in aws-geospatial/amazon-location-mobile-auth-sdk-android#17 since the issue is now isolated to that project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants