Distribution plugin does not include transformed artifacts

I try to use the distribution plugin together with the extra-java-module-info plugin. The latter is used to enrich non-JPMS dependencies by module information. However, the resulting archive only contains the untransformed dependencies, not the enriched ones. Is this a known problem or am I doing something wrong? I am currently using Gradle 8.9.

The configuration for extra-java-module-info plugin is as follows:

    extraJavaModuleInfo {
        module('org.reactfx:reactfx', 'org.reactfx.reactfx') {
            exportAllPackages()
            requireAllDefinedDependencies()
            requiresTransitive('javafx.base')
            requiresTransitive('javafx.controls')
            requiresTransitive('javafx.graphics')
        }
        // ...more libraries...
    }

The configuration for distribution plugin is:

distributions {
    main {
        distributionBaseName = 'FileAnalyser'
    }
}

The resulting archive does not contain the transformed JAR files. So starting the application chokes on the libraries without module information:

$ bin/GUI
Error occurred during initialization of boot layer
java.lang.module.FindException: Module org.reactfx.reactfx not found, required by de.set.fileanalyser.gui

For the same reason, the “run” task from the application plugin does not work either and produces the same error message. But the transformed artifacts do exist and are e.g. written into the .classpath files when using the eclipse plugin, so running from the Eclipse IDE just works.

Any help is much appreciated.

Regards,
Christoph

The plugin configures the runtime classpath, compile classpath, and annotation processor classpath of all source sets to do the transformation.
And as the runtime classpath should be the one used for the run task and the distribution, it should usually work.
Can you provide an MCVE where it does not work?

Thank you for your reply. Mentioning the runtime classpath rang a bell, so I looked in my build scripts again and found the following block:

    pluginManager.withPlugin('java-library') {
        configurations {
            runtimeClasspath {
                attributes { attribute(Attribute.of("javaModule", Boolean), false) }
            }
            testRuntimeClasspath {
                attributes { attribute(Attribute.of("javaModule", Boolean), false) }
            }
        }
    }

Removing it made it work!

However, this was the workaround I used to make testing work. I had it from the plugin description found here:

How do I combine the distribution plugin and the extra-java-module-info plugin so that it does not break testing via JUnit 5? If I remove the block above, any project relying on a non-modularized test fixture project produces an error like the following one:

> Task :IO:File:test FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':IO:File:test'.
> Could not resolve all files for configuration ':IO:File:testRuntimeClasspath'.
   > Failed to transform JUnit-0.1-test-fixtures.jar (project :Testing:JUnit) to match attributes {artifactType=jar, javaModule=true, org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.jvm.version=17, org.gradle.libraryelements=jar, org.gradle.usage=java-runtime}.
      > Execution failed for ExtraJavaModuleInfoTransform: C:\Source\PrintDataTools\Testing\JUnit\build\libs\JUnit-0.1-test-fixtures.jar.
         > Not a module and no mapping defined: JUnit-0.1-test-fixtures.jar
   > Failed to transform JUnit-0.1.jar (project :Testing:JUnit) to match attributes {artifactType=jar, javaModule=true, org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.jvm.version=17, org.gradle.libraryelements=jar, org.gradle.usage=java-runtime}.
      > Execution failed for ExtraJavaModuleInfoTransform: C:\Source\PrintDataTools\Testing\JUnit\build\libs\JUnit-0.1.jar.
         > Not a module and no mapping defined: JUnit-0.1.jar

Thank you in advance,
Christoph

You misread the docs you sent.
It shows how you can disable for a specific configuration and uses as example the runtimeClasspath.
It also describes that for building a bad-practice fat jar the runtimeClasspath could indeed be one you want to change as it is irrelevant there anyway.
It also describes that for non-modular testing you might want to disable it for testRuntimeClasspath.
You disabled it for both.

Besides that and the error you posted last, well, the plugin assumes by default that you want to have everything as module. You can for example configure the plugin to not fail on missing module info.

Or you could define mappings for those two jar files too, or actually as they are part of your build you could just make them proper modules or at least automatic modules unless you enabled that the plugin also complains if any automatic modules are found.

Btw. I strongly recommend switching to Kotlin DSL. By now it is the default DSL, you immediately get type-safe build scripts, actually helpful error messages if you mess up the syntax, and amazingly better IDE support if you use a good IDE like IntelliJ IDEA or Android Studio.

After disabling for testRuntimeClasspath configuration only it works as expected. Thank you very much!

1 Like