Overriding java plugin configuration hierarchy

Hi everyone,

I’m looking at converting an existing Ant + Ivy build over to Gradle. We have several java sub-projects that are used within a J2EE container as well as standalone. These projects may depend on resources provided by the container, so we have different configurations in Ivy that indicate the dependencies for each use case.

Ivy Configurations

  • compile: all compile time dependencies, including container dependencies
  • container: all runtime dependencies required when used in a container. This module doesn’t include dependencies provided by the J2EE container
  • standalone: all runtime dependencies, including those which would have normally been provided from a container.

There is no extension between our current Ivy configurations, but logically standalone includes everything in container. Occasionally there is something included in compile that is not in the others (e.g. findbugs annotations).

I’ve tried to reproduce this functionally in gradle. Here is my intended configuration in gradle.

I use one of these configurations when declaring dependencies

  • container: dependencies provided by the J2EE container
  • runtimeContainer: runtime dependencies that are needed while running in the container
  • provided: dependencies used at compile time but not at runtime
  • testCompile: dependencies used for the test source

I then mark these as extending some combination of the configurations above:

  • runtime - extends runtimecontainer and container; all runtime dependencies for running standalone
  • compile - extends runtime and provided

When I do all of this, gradle task gives me a StackOverflowError. The following build.gradle demonstrates the setup and error, if you run gradle dependencies:

apply plugin: "java"

configurations {
    container
    provided
    runtimeContainer


    runtime.extendsFrom = [container, runtimeContainer]
    compile.extendsFrom = [provided, runtime]
    testRuntime.extendsFrom = [runtime]
    testCompile.extendsFrom = [testRuntime]
}

How can I setup my dependency configurations to enable me to handle my projects being used with and without a J2EE container?

"provided: dependencies used at compile time but not at runtime"
That’s almost the definition for the gradle ‘compile’ configuration.

Since you’re using conventionally agreed (by the Java plugin) configuration names, some things you do are not possible.
With the Java plug-in, for instance, testRuntime extends testCompile. Your setting makes testCompile extends from testRuntime, leading to the overflow.

You can completely bypass the conventional configurations, to model your ivy settings.

Your compile configuration extends from the runtime configuration. It really should be the other way around.

Thanks for the reply. I took your advice and just bypassed most of the conventional configurations.

My configuration block now looks like this, which adds the runtimeContainer configuration and breaks the extends between the runtime and compile configurations. This means later on I manually add the runtime or testRuntime configuration too the compileClasspath for the source sets.

 configurations {
    runtimeContainer

    runtime.extendsFrom = [runtimeContainer]
    testRuntime.extendsFrom -= [testCompile]
}

And then I can use the configurations as follows:

  • runtimeContainer: dependencies needed at runtime within a container
  • runtime: additional runtime dependencies needed when not using a container
  • compile: compile time only dependencies (e.g. findbugs annotations)
  • testRuntime: dependencies needed at test runtime
  • testCompile: test compile time only dependencies

Glad you found a short and clean configurations setting