Java ToolChain present in allProjects block is no applied to subproject unless "apply plugin: java" is in the block

is it possible that the java extension block has failed for these projects and hence the extension setting were failed to apply for all the other sub projects as well?

No, the problem is, that you only configure the java extension of the root project.
If you add:

println("FOO: ${System.identityHashCode(java)}")
allprojects {
    println("BAR: ${System.identityHashCode(java)}")
}

you will see that always the root extension is configured.
If you change it to:

println("FOO: ${System.identityHashCode(java)}")
allprojects {
    apply plugin: 'java'
    println("BAR: ${System.identityHashCode(java)}")
}

you see that the subprojects’ extensions are configured.
If you change it to (don’t do this in reality, just showcasing):

println("FOO: ${System.identityHashCode(java)}")
allprojects {
    afterEvaluate {
        println("BAR: ${System.identityHashCode(java)}")
    }
}

you also see that the subprojects’ extensions are configured.

At the time your extension configuration is done on the subprojects, the Java plugin is not applied yet and because of that, it configures the Java extension of the root project instead.
By applying the java plugin before or by delaying the execution (again, don’t do this) the extension in the subproject is already there and can be configured.

I have two recommendations for you.

  1. Consider switching from Groovy DSL to Kotlin DSL. This is by now the recommended default DSL, it immediately gives you type-safe build scripts, it gives you actually helpful error messages if you mess up the syntax, and you get amazingly better IDE support when using a proper IDE like IntelliJ IDEA.
  2. Do not use allprojects { ... }, subprojects { ... }, project(...) { ... } or similar. Those are bad practice and immediately introduce project coupling by doing cross-project configuration. This disturbs more sophisticated Gradle features and even prevents some upcoming features to work properly. Instead you should use convention plugins, for example in buildSrc or and included build, for example implemented as precompiled script plugins. Those you can then targetedly apply to the projects where their effect should be present, so that you for example only apply Java conventions to projects that are actually Java projects.

If you want to continue the bad practice of using allprojects { ... }, you could at least mitigate your problem by reacting to the java-base plugin being applied to the project in question which is the one that adds the Java extension like:

println("FOO: ${System.identityHashCode(java)}")
allprojects {
    pluginManager.withPlugin("java-base") {
        println("BAR: ${System.identityHashCode(java)}")
    }
}
1 Like