When should we use 'java' plugin and when 'java-library' plugin?

(Szczepan Faber) #1

Hey guys!

When should we use ‘java’ plugin and when ‘java-library’ plugin? The user guide chapter is not clear about it. Is the future direction that ‘java’ will get deprecated in favor of ‘java-library’ plugin which has fantastic benefits like compile avoidance and cleaner classpaths.

Our use case at LinkedIn is following: should we automatically apply ‘java-library’ plugin to all our few thousand projects that currently use ‘java’? Is this a compatible change that we can safely do?

The docs say that: “compile, testCompile, runtime and testRuntime configurations inherited from the Java plugin are still available but are deprecated”. Does it mean that in the future version of Gradle, the build will fail when a “java-library” project still has dependencies declared in the deprecated configurations? For us it is important because we can evaluate the future migration cost.

Thank you in advance for pointers!

PS. Suggestion: mention in the doc that ‘java-library’ applies ‘java’.

(Cédric Champeau) #2

Hi Szczepan,

Basically, if you build a library (aka, a component meant to be consumed by other components), you should use the java-library plugin instead of the java plugin. In most cases it’s as straightforward as what you describe, that is to say change from apply plugin: 'java' to apply plugin: 'java-library'.

Independently of whether you are using the java-library plugin or not, it’s strongly recommended to move to the implementation configuration (instead of compile). The api configuration is only available with the java-library plugin obviously. And yes, in an undetermined future version of Gradle, the compile configuration and other “soft deprecated” configurations are going to be removed. We reckon that the migration may take a while, so that’s why it’s a much longer deprecation cycle than usual.

Eventually, there are corner cases with the java-library plugin which are not (yet) covered, like if you use cross-compilation (Java + Groovy, Java + Kotlin). That would only make the migration harder, but not impossible.

Does that help?

(Felix) #3

From my understanding multi-projects build can benefit from using ‘java-library’ by keeping the compile classpath of the referencing sub-projects (the clients of the libraries) small - only the ‘api’ jars listed in each library sub-project are included in their compile classpathes.

(mauromol) #4

I can’t find any reference right now, but I remember I read something about WAR projects applying java-library plugin having problems deploying dependencies declared in the implementation configuration, or something like that. So WAR projects could be a case where the new java-library plugin and its configurations should not be currently used, although I guess they can be used on projects those WAR projects depend on (correct me if I’m wrong).

@CedricChampeau could you please elaborate more on the topic Java+Groovy (or Java+Kotlin) and not being able to use the java-library plugin currently?

(Cédric Champeau) #5

@mauromol this is actually in the docs, see known limitations: https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_known_issues

(sergey.morenets) #6

Hi @CedricChampeau

Thank you for the explanation. What are the best practices for java-library plugin?
For example, I have two projects: project1 and project2. Project2 depends on project1 and both projects use library1(for implementation). Which option should we use?

  1. Declare library1 in implementation configuration of both projects.
  2. Declare library1 in compile configuration for project1.

(Sebastian Schuberth) #7

Does that known limitation and piece of code on that page apply to using Kotlin with the java-library plugin (i.e. writing a library in Kotlin using the java-library plugin), too, and can it be applied by simply exchanging compileGroovy with compileKotlin?

Edit: Apparently not, as I’m getting

ConfigurationVariant with name 'classes' not found.