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

firebase-crashlytics-buildtools has an undeclared dependency on org.apache.httpcomponents:httpclient #5473

Open
yogurtearl opened this issue Oct 24, 2023 · 7 comments

Comments

@yogurtearl
Copy link

yogurtearl commented Oct 24, 2023

[READ] Step 1: Are you in the right place?

yes

[REQUIRED] Step 2: Describe your environment

  • Gradle version: 8.4
  • AGP version: 8.1.2
  • Firebase Component: Crashlytics gradle plugin
  • Component version: 2.9.9

[REQUIRED] Step 3: Describe the problem

Steps to reproduce:

Apply the firebase gradle plugin via a precompiled script plugin in build-logic/

i.e. at build-logic/src/main/kotlin/firebase.gradle.kts you would have:

plugins {
    id("com.google.firebase.crashlytics")
}

that plugin uses org.apache.http.client.methods.HttpRequestBase which comes from org.apache.httpcomponents:httpclient but the pom.xml does NOT declare this dependency.

This pom needs to add org.apache.httpcomponents:httpclient as a dependency:
https://dl.google.com/android/maven2/com/google/firebase/firebase-crashlytics-buildtools/2.9.9/firebase-crashlytics-buildtools-2.9.9.pom

See error below.

workaround

Add this to your build-logic/build.gradle.kts :

plugins {
   `kotlin-dsl`
}

dependencies {
    // workaround for https://github.com/firebase/firebase-android-sdk/issues/5473
    implementation("org.apache.httpcomponents:httpclient:4.5.5")

    implementation("com.google.firebase.crashlytics:com.google.firebase.crashlytics.gradle.plugin:2.9.9")
}

ERROR

Caused by: java.lang.NoClassDefFoundError: org/apache/http/client/methods/HttpRequestBase
	at com.google.firebase.crashlytics.buildtools.Buildtools.createWebApi(Buildtools.java:64)
	at com.google.firebase.crashlytics.buildtools.Buildtools.getInstance(Buildtools.java:107)
	at com.google.firebase.crashlytics.buildtools.Buildtools$getInstance$0.call(Unknown Source)
	at com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsPlugin.configureBuildtools(CrashlyticsPlugin.groovy:133)
	at com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsPlugin.apply(CrashlyticsPlugin.groovy:73)
	at com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsPlugin.apply(CrashlyticsPlugin.groovy)
	at org.gradle.api.internal.plugins.ImperativeOnlyPluginTarget.applyImperative(ImperativeOnlyPluginTarget.java:43)
	at org.gradle.api.internal.plugins.RuleBasedPluginTarget.applyImperative(RuleBasedPluginTarget.java:51)
	at org.gradle.api.internal.plugins.DefaultPluginManager.addPlugin(DefaultPluginManager.java:187)
	at org.gradle.api.internal.plugins.DefaultPluginManager.access$100(DefaultPluginManager.java:52)
	at org.gradle.api.internal.plugins.DefaultPluginManager$AddPluginBuildOperation.run(DefaultPluginManager.java:282)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:73)
	at org.gradle.api.internal.plugins.DefaultPluginManager.lambda$doApply$0(DefaultPluginManager.java:167)
	at org.gradle.configuration.internal.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:44)
	at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:166)
	at org.gradle.api.internal.plugins.DefaultPluginManager.apply(DefaultPluginManager.java:137)
	at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.lambda$applyPlugin$1(DefaultPluginRequestApplicator.java:181)
	at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugin(DefaultPluginRequestApplicator.java:233)
	at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugin(DefaultPluginRequestApplicator.java:179)
	at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.access$200(DefaultPluginRequestApplicator.java:63)
	at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator$1$1.lambda$add$1(DefaultPluginRequestApplicator.java:156)
	at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.lambda$applyPlugins$0(DefaultPluginRequestApplicator.java:108)
	at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugins(DefaultPluginRequestApplicator.java:108)
	at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugins(DefaultPluginRequestApplicator.java:139)
	at org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessorsKt.applyPlugins(GeneratePrecompiledScriptPluginAccessors.kt:512)
	at org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessorsKt.access$applyPlugins(GeneratePrecompiledScriptPluginAccessors.kt:1)
	at org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors$projectSchemaFor$1$1$1.call(GeneratePrecompiledScriptPluginAccessors.kt:366)
	at org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors$projectSchemaFor$1$1$1.call(GeneratePrecompiledScriptPluginAccessors.kt:350)
	at org.gradle.internal.Try.ofFailable(Try.java:41)
	at org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors$projectSchemaFor$1$1.apply(GeneratePrecompiledScriptPluginAccessors.kt:350)
	at org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors$projectSchemaFor$1$1.apply(GeneratePrecompiledScriptPluginAccessors.kt:349)
	at org.gradle.internal.build.DefaultBuildLifecycleController.lambda$withSettings$0(DefaultBuildLifecycleController.java:123)
	at org.gradle.internal.model.StateTransitionController.lambda$notInState$3(StateTransitionController.java:132)
	at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:44)
	at org.gradle.internal.model.StateTransitionController.notInState(StateTransitionController.java:128)
	at org.gradle.internal.build.DefaultBuildLifecycleController.withSettings(DefaultBuildLifecycleController.java:123)
	at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.lambda$withEmptyBuild$3(DefaultBuildTreeLifecycleController.java:89)
	at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.lambda$runBuild$4(DefaultBuildTreeLifecycleController.java:98)
	at org.gradle.internal.model.StateTransitionController.lambda$transition$6(StateTransitionController.java:169)
	at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:266)
	at org.gradle.internal.model.StateTransitionController.lambda$transition$7(StateTransitionController.java:169)
	at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:44)
	at org.gradle.internal.model.StateTransitionController.transition(StateTransitionController.java:169)
	at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.runBuild(DefaultBuildTreeLifecycleController.java:95)
	at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.withEmptyBuild(DefaultBuildTreeLifecycleController.java:88)
	at org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors$projectSchemaFor$1.apply(GeneratePrecompiledScriptPluginAccessors.kt:349)
	at org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors$projectSchemaFor$1.apply(GeneratePrecompiledScriptPluginAccessors.kt:348)
	at org.gradle.composite.internal.RootOfNestedBuildTree$1.call(RootOfNestedBuildTree.java:137)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:78)
	at org.gradle.composite.internal.RootOfNestedBuildTree.run(RootOfNestedBuildTree.java:134)
	at org.gradle.composite.internal.DefaultNestedBuildTree.run(DefaultNestedBuildTree.java:80)
	at org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors.projectSchemaFor(GeneratePrecompiledScriptPluginAccessors.kt:348)
	at org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors.access$projectSchemaFor(GeneratePrecompiledScriptPluginAccessors.kt:85)
	at org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors$projectSchemaImpliedByPluginGroups$1$1.invoke(GeneratePrecompiledScriptPluginAccessors.kt:325)
	at org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessors$projectSchemaImpliedByPluginGroups$1$1.invoke(GeneratePrecompiledScriptPluginAccessors.kt:323)
	at org.gradle.kotlin.dsl.provider.plugins.precompiled.tasks.GeneratePrecompiledScriptPluginAccessorsKt.withCapturedOutputOnError(GeneratePrecompiledScriptPluginAccessors.kt:531)
	... 131 more
Caused by: java.lang.ClassNotFoundException: org.apache.http.client.methods.HttpRequestBase
	at org.gradle.internal.classloader.VisitableURLClassLoader$InstrumentingVisitableURLClassLoader.findClass(VisitableURLClassLoader.java:186)
	... 201 more
@argzdev
Copy link
Contributor

argzdev commented Oct 30, 2023

Hi @yogurtearl, thanks for reaching out. While we investigate this, any chance you could share a minimal reproducible example of the issue? Thanks!

@mrober
Copy link
Contributor

mrober commented Oct 31, 2023

Are you intending to extend the plugin or something? I am curious why you apply it this was as a dep in your build-logic, instead of applied as a typical gradle plugin? The issue might have something to do with that, I can play with it but I want to understand the use case more please.

@google-oss-bot
Copy link
Contributor

Hey @yogurtearl. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

@yogurtearl
Copy link
Author

I have a precompiled script plugin that applies the firebase plugin, but because it is not declaring it's deps properly it fails when gradle tries to generate the accessors.

@yogurtearl
Copy link
Author

yogurtearl commented Nov 7, 2023

This script will reproduce the issue on macOS, assuming you have gradle 8.x installed locally.

This uses the built in kotlin-dsl plugin to create a precompiled script plugin.
https://docs.gradle.org/current/userguide/custom_plugins.html#sec:precompiled_plugins

#!/usr/bin/env zsh

tmpdir=$(/usr/bin/mktemp -d /tmp/repro_5473.XXXXXX)

cd "$tmpdir" || exit

mkdir -p "$tmpdir/src/main/kotlin/"

cat <<"BUILD_FILE" > "$tmpdir/build.gradle.kts"
plugins {
    `kotlin-dsl`
}

repositories {
    google()
    mavenCentral()
}

dependencies {
    implementation("com.google.firebase.crashlytics:com.google.firebase.crashlytics.gradle.plugin:2.9.9")
}
BUILD_FILE

cat <<"PLUGIN_FILE" > "$tmpdir/src/main/kotlin/myplugin.gradle.kts"
plugins {
    id("com.google.firebase.crashlytics")
}
PLUGIN_FILE

gradle build --stacktrace

echo "$tmpdir"

will result in:

Caused by: java.lang.NoClassDefFoundError: org/apache/http/client/methods/HttpRequestBase
        at com.google.firebase.crashlytics.buildtools.Buildtools.createWebApi(Buildtools.java:64)
        at com.google.firebase.crashlytics.buildtools.Buildtools.getInstance(Buildtools.java:107)
        at com.google.firebase.crashlytics.buildtools.Buildtools$getInstance$0.call(Unknown Source)
        at com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsPlugin.configureBuildtools(CrashlyticsPlugin.groovy:133)
        at com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsPlugin.apply(CrashlyticsPlugin.groovy:73)
        at com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsPlugin.apply(CrashlyticsPlugin.groovy)
        at org.gradle.api.internal.plugins.ImperativeOnlyPluginTarget.applyImperative(ImperativeOnlyPluginTarget.java:43)
.
.
Caused by: java.lang.ClassNotFoundException: org.apache.http.client.methods.HttpRequestBase
        at org.gradle.internal.classloader.VisitableURLClassLoader$InstrumentingVisitableURLClassLoader.findClass(VisitableURLClassLoader.java:186)
        ... 196 more


BUILD FAILED in 1s
4 actionable tasks: 4 executed

This can be fixed by adding the httpclient dependency to your published pom file.

https://dl.google.com/android/maven2/com/google/firebase/firebase-crashlytics-buildtools/2.9.9/firebase-crashlytics-buildtools-2.9.9.pom

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.14</version>
</dependency>

@yogurtearl
Copy link
Author

Is the source code for the firebase crashlytics gradle plugin open source?

@mrober mrober self-assigned this Nov 10, 2023
@mrober
Copy link
Contributor

mrober commented Feb 22, 2024

Unfortunately is it not open sourced. I am advocating for open sourcing our Gradle plugin, but it is not a high priority right now.

I have a hunch your issue is caused by a failure in the way we package the fat jar. We do include httpclient, but we also namespace it so it does not interfere with your other Gradle plugins that may depend on an incompatible version of httpclient. We validate it with the typical workflow, that is simply applying the plugin in a project. Your workflow is different, and we don't have a functional test for it. I will add one, and fix the fat jar, but it might not happen until other high priority issues are addressed first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants