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

java.lang.NoClassDefFoundError: org/gradle/kotlin/dsl/PluginAwareExtensionsKt when applying plugin to a Project with a sub Project during tests #1123

Open
sihutch opened this issue Feb 5, 2024 · 1 comment
Labels
bug Something isn't working testing toolchain:kotlin
Milestone

Comments

@sihutch
Copy link

sihutch commented Feb 5, 2024

Build scan link
https://scans.gradle.com/s/segppkfrzjmca/

Plugin version
1.29.0

Gradle version
7.6.1 (Same bug exhibits with Gradle 8.0)

JDK version
11.0.16 (Amazon.com Inc. 11.0.16+8-LTS)

Describe the bug

We have tests that build Projects using org.gradle.testfixtures.ProjectBuilder. We apply the com.autonomousapps.dependency-analysis plugin on the Project during our test. If the test Project does not have a sub Project then plugin application works. However, if the test Project does have a sub Project, then a
java.lang.NoClassDefFoundError: org/gradle/kotlin/dsl/PluginAwareExtensionsKt exception is thrown when the com.autonomousapps.subplugin.RootPlugin attempts to conditionallyApplyToSubprojects as shown in the snippet from the stack trace below (The full stack trace can be seen on the build scan here)

Caused by: java.lang.NoClassDefFoundError: org/gradle/kotlin/dsl/PluginAwareExtensionsKt
com.autonomousapps.subplugin.RootPlugin$conditionallyApplyToSubprojects$1.execute(RootPlugin.kt:65) |  
com.autonomousapps.subplugin.RootPlugin$conditionallyApplyToSubprojects$1.execute(RootPlugin.kt:63)

To Reproduce
Steps to reproduce the behavior:

  1. Build a org.gradle.api.Project using the org.gradle.testfixtures.ProjectBuilder
  2. Build a second org.gradle.api.Project using the org.gradle.testfixtures.ProjectBuilder setting the Project from step 1 as its parent
  3. Apply the com.autonomousapps.dependency-analysis plugin to the root project

I created a Junit 5 test to help me diagnose and have included it below (note this test fails as the NoClassDefFoundError exception is thrown)

Also note that if we remove the line ProjectBuilder.builder().withParent(rootProject).build(); from the code, then the test passes.

package org.example;

import org.gradle.api.Project;
import org.gradle.testfixtures.ProjectBuilder;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;

public class ProjectBuilderTest {

    @DisplayName("Ensure that the dependency-analysis plugin can be applied on a textfixtures project with a subproject")
    @Test
    void canApplyPluginOnProjectWithSubProject() {
        Project rootProject = ProjectBuilder.builder().build();
        ProjectBuilder.builder().withParent(rootProject).build();
        assertDoesNotThrow(() ->
                rootProject.getPluginManager().apply("com.autonomousapps.dependency-analysis"));
    }
}

Expected behavior
We expect the plugin application to work on a Project containing a sub Project in the same way as it does on a Project without any sub Project.

Additional context
I'm not sure that is related, but I noticed this line [Fix] Don't leak Kotlin stdlib from shaded dependencies. from the 1.29.0 release notes.

I tested against the previous plugin version, i.e. 1.28.0. On this version, a Kotlin java.lang.NoClassDefFoundError is thrown when we apply the plugin on any Project in our test, i.e. even if the Project does not have any sub Project.

Notice from the stack trace below that for version 1.28.0, the exception was thrown by a call to com.autonomousapps.DependencyAnalysisPlugin.applyForProject as opposed to version 1.29.0 where the exception was thrown by a call to com.autonomousapps.subplugin.RootPlugin$conditionallyApplyToSubprojects

Caused by: java.lang.NoClassDefFoundError: org/gradle/kotlin/dsl/NamedDomainObjectCollectionExtensionsKt
	at com.autonomousapps.subplugin.ProjectPlugin.<clinit>(ProjectPlugin.kt:55)
	at com.autonomousapps.DependencyAnalysisPlugin.applyForProject(DependencyAnalysisPlugin.kt:83)
	at com.autonomousapps.DependencyAnalysisPlugin.apply(DependencyAnalysisPlugin.kt:28)
	at com.autonomousapps.DependencyAnalysisPlugin.apply(DependencyAnalysisPlugin.kt:22)

I included this context as it appears that something related was fixed in the 1.29.0 release but that it somehow wasn't fixed for the sub Project case.

@autonomousapps autonomousapps added this to the after next milestone Feb 6, 2024
@autonomousapps
Copy link
Owner

Thanks for the issue. Looks like some kind of classpath issue. It reminds me of a case in a real (non-test) project that uses Kotlin but wasn't applying any Kotlin plugin to the root project. I am not entirely sure how the classpath works in the context of a unit test like you have, but as I stare at the error and the build scan you shared, it occurs to me that my plugin uses Kotlin DSL, and that missing class is from the Kotlin DSL -- that is, the Gradle jar itself. Maybe try adding testRuntimeOnly(gradleApi()) to your build script. That may not work though because I'm not certain that dependencies also contains the Kotlin DSL classes. My IDE tells me that class comes from gradle-kotlin-dsl-8.5.jar.

More generally, I'm not sure it makes a lot of sense to try to unit test this. I recommend writing functional tests instead. I have a plugin and companion libraries for that here if you're interested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working testing toolchain:kotlin
Projects
None yet
Development

No branches or pull requests

2 participants