Gradle Java Plugin: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(275 intermediate revisions by the same user not shown)
Line 1: Line 1:
=External=
=External=
* https://docs.gradle.org/current/userguide/java_plugin.html
* https://docs.gradle.org/current/userguide/java_plugin.html
=Internal=
=Internal=
 
* [[Gradle_Plugin_Concepts#Core_Plugins|Gradle Plugins | Core Plugins]]
* [[Gradle Concepts#Gradle_Java_Plugin|Gradle Concepts]]
* [[Gradle Java Library Plugin|Java Library Plugin]]
* [[Gradle Dependencies and Dependency Configurations]]


=Overview=
=Overview=
 
The Java plugin adds Java compilation, testing and packaging capabilities to a project.
The Java plugin adds [[Gradle Concepts#Task|tasks]] to your [[Gradle Concepts#Project|project]] which will compile and unit test your Java source code, and bundle it into a JAR file. The Java plugin is [[#Plugin_Conventions|convention]] based. This means that the plugin defines default values for many aspects of the project, such as where the Java source files are located.  If you follow the convention in your project, you generally don’t need to do much in your build script to get a useful build. To use it, [[build.gradle]] must include:
 
<syntaxhighlight lang='groovy'>
<syntaxhighlight lang='groovy'>
apply plugin: 'java'
plugins {
  id 'java'
}
</syntaxhighlight>
</syntaxhighlight>
The Java plugin also serves as the basis for many of the other JVM language Gradle plugins. The Java plugin builds upon a Java Base plugin.


This is all you need to define a Java project, provided that [[#Plugin_Conventions|plugin's conventions]] are followed.
However, it is the Java Library plugin that should be used by default with Java projects instead of Java plugin. Java Library plugin extends the Java plugin, so it offers all the features of the Java plugin, plus a set of additional ones: {{Internal|Gradle_Java_Library_Plugin#Overview|Java Library Plugin}}
The Java plugin instantiates by default two [[#Source_Set|source sets]] ("main" and "test"). Each of these source sets has an associated compile task: [[#compileJava|compileJava]] (which is the abbreviation of "compileMainJava") for the "main" source set and [[#compileTestJava|compileTestJava]] for the "test" source set. To compile the production and test code:
* put the production source code in 'src/main/java' directory.
* put the test source code under 'src/test/java' directory.
* declare your production compile dependencies in the [[Gradle_Dependencies_and_Dependency_Configurations#compileOnly|compileOnly]] or [[Gradle_Dependencies_and_Dependency_Configurations#implementation|implementation]] configurations.
* declare your test compile dependencies in the [[Gradle_Dependencies_and_Dependency_Configurations#testCompileOnly|testCompileOnly]] or [[Gradle_Dependencies_and_Dependency_Configurations#testImplementation|testImplementation]] configurations.
* Run the [[#compileJava|compileJava]] task for the production code and [[#compileTestJava|compileTestJava]] for the tests.


The plugin adds "main" and "test" sourceSets, and initializes its variables as runtimeClasspath.
The Java plugin also adds a [[#jar|jar]] task that assembles a JAR file with the classes produced from the "main" source set code.


The plugin adds a "java" [[Gradle_Concepts#Software_Component|software component]] accessible via components.java. The artifact associated with the Java component is the generated JAR file, and the dependencies are those of the [[#runtime|runtime]] configurations.
The default configuration of the source sets is convention-based, borrowing the directory layout from Maven projects. As such, if those conventions are followed, generally not much needs to be added to the build script to get a useful build.


=Plugin Conventions=
=Concepts=
==Source Set==
{{External|https://docs.gradle.org/current/dsl/org.gradle.api.tasks.SourceSet.html}}
A source set is a logical grouping of source files and resources, typically associated on the base of their purpose: application production code, test code, etc. Each source set contains sources and resources from typically one, but possibly more directories, which are listed as part of the source set. The files that form a source set '''don't have to be located in the same directory'''. The source set concept was introduced by the Java plugin. A source set directory has subdirectories for java sources, and other types of sources. The Java plugin instantiates by default two source sets: [[#main_SourceSet|main]] and [[#test_SourceSet|test]]. They correspond to the conventional directories from "src":
<syntaxhighlight lang='text'>
.
└─ src
  ├─ main                  ← source set "main"
  │    ├─ java            ← the java subtree of the "main" source set
  │    │    └─ playground
  │    │        └─ Sample.java
  │    └─ resources        ← the resource subtree of the "main" source set
  │
  └─ test                  ← source set "test"
        ├─ java            ← the java subtree of the "test" source set
        │    └─ playground
        │        └─ SampleTest.java
        └─ resources        ← the resource subtree of the "test" source set


==Conventional Project Layout==
</syntaxhighlight>
<span id='SourceSet_Configuration'></span>Aside from the source files and resources, the source set also keeps track of various classpaths, including any dependencies, require the compile or run the code. It does that by maintaining a set of '''[[Gradle_Dependencies_and_Dependency_Configurations#Configuration|configurations]]''' corresponding to the compilation classpath, annotation processor classpath and runtime classpath. Each source set has associated an "<''source-set-name''>implementation" configuration. In case of the "main" source set, main is omitted and the configuration is named simply "implementation". Also see: {{Internal|Gradle_Dependencies_and_Dependency_Configurations#Dependency|Configuration}}


{{External|https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_project_layout}}
Finally, the source set keeps track of where the compiled class files are placed, as a source set '''output'''.


The Java plugin expects to find the production source code under:
The Java plugin automatically creates compilation tasks for each source set, naming them "compile<''source-set-name''>Java". In case of the "main" source set, the <source-set-name> is omitted and the task is called "[[#compileJava|compileJava]]".


src/main/java


Tests are expected under:
[[Image:SourceSet.png|center|480px]]


src/test/java


All files under:
Each source set is internally maintained in the runtime project hierarchy as child of the Java plugin. However, it can be configured via a top-level script blocks:
<syntaxhighlight lang='groovy'>
plugins {
  id 'java'
}
sourceSets {
  main {
    java {
      srcDirs = ['src/main/java']
    }
    resources {
      srcDirs = ['src/main/resources']
      excludes = ['**/something/**']
    }
  }
  test {
    java {
      srcDirs = ['src/test/java']
    }
    resources {
      srcDirs = ['src/test/resources']
      excludes = ['**/something/**']
    }
  }
}
</syntaxhighlight>


src/main/resources
More details on how to reconfigure existing source sets is available below in the section [[#Source_Set_Customization|Source Set Customization]].


are considered resources and they will be include in the JAR, as resources.
===Source Set Lifecycle===
<font color=darkgray>How is a source set configured during the project lifecycle? How are configurations injected?</font>
===Resource Files===
Java projects typically include resource other than source files, such as property files, that may need processing - for example by replacing tokens within the files - and packaging them within the final JAR. Typical use cases for resource files are images, configuration files, localization data. The Java plugin handles this automatically by creating a dedicated task for each source set, called "process<''source-set-name''>Resources", or "[[#processResources|processResources]]" for the main source set. The processing consists in copying files from src/<''source-set''>/resources to a directory that will be included in the project's JAR. This target directory will also be included in the runtime classpath of the tests.


The files available under:
===Default Source Sets===
====<span id='main_SourceSet'></span>The "main" Source Set====
The main source set is conventionally associated with all source files found under src/main/java and all resource files from src/main/resources. The sources managed by the main source set are compiled by the [[#compileJava|compileJava]] task. The resources are processed by the [[#processResources|processResources]] task. The main source set is associated with the "[[Gradle_Dependencies_and_Dependency_Configurations#compileOnly|compileOnly]]", "[[Gradle_Dependencies_and_Dependency_Configurations#runtimeOnly|runtimeOnly]]" and "[[Gradle_Dependencies_and_Dependency_Configurations#implementation|implementation]]" configurations. The [[#jar|jar]] task packages the main source set compiled classes and resources.
<syntaxhighlight lang='text'>
└─ src
    └─ main
        ├─ java
        └─ resources
</syntaxhighlight>


src/test/resources
====<span id='test_SourceSet'></span>The "test" Source Set====
 
The "test" source set is conventionally associated with all the source file under src/test/java. It contains test source code, which is compiled and executed using JUnit or TestNG. These are typically unit tests, but any test can be include in this source set as long as they all share the same compilation and runtime classpaths. The sources managed by the "test" source set are compiled by the [[#compileTestJava|compileTestJava]] task, and the tests are executed by the [[#test|test]] task. The resources are processed by the [[#processTestResources|processTestResources]] task. The test source set is associated with the "[[Gradle_Dependencies_and_Dependency_Configurations#testCompileOnly|testCompileOnly]]", "[[Gradle_Dependencies_and_Dependency_Configurations#testRuntimeOnly|testRuntimeOnly]]" and "[[Gradle_Dependencies_and_Dependency_Configurations#testImplementation|testImplementation]]" configurations.
are considered test resources and will be included in the classpath used to run tests.
<syntaxhighlight lang='text'>
└─ src
    └─ test
        ├─ java
        └─ resources
</syntaxhighlight>


All output files are created under the:
===Custom Source Set===
New source sets can be defined, typically for one or both of the following reasons:
* The source code should be keep separate from the existing source sets for aesthetics and manageability.
* The source code requires a different, unique compilation or runtime classpaths.
* The generated code should be handled differently than the code from main and test source set.


build
==Java Toolchain==


directory.  
The toolchain options protect against problems with the project being built with different Java versions.


The JAR file is created in:  
<font color=darkgray>TODO: https://docs.gradle.org/current/userguide/toolchains.html</font>.
==Component==


build/libs
The plugin adds a "java" [[Gradle Software Components#Overview|software component]] accessible via <code>components.java</code>. The JAR file produced by the [[#jar|jar]] task is the artifact associated with the Java component, <font color=darkgray>and its dependencies are those of the [[Gradle_Dependencies_and_Dependency_Configurations#runtime|runtime]] configuration.</font>


=Dependency Configurations=
=Dependency Configurations=
{{Internal|Gradle_Dependencies_and_Dependency_Configurations#Default_Configurations_added_by_the_Java_Plugin|Default Configurations added by the Java Plugin}}


{{External|https://docs.gradle.org/current/userguide/java_plugin.html#tab:configurations}}
=Tasks=
==<tt>compileJava</tt>==
The "compileJava" task compiles the sources managed by the [[#The_.22main.22_Source_Set|"main" source set]]. The task is backed by the [[Gradle JavaCompile Task Type#Overview|JavaCompile]] type.


The Java plugin adds the following [[Gradle_Concepts#Dependency_Configuration|dependency configurations]] to the project:
To change compiler options, configure the task as follows:
<syntaxhighlight lang='groovy'>
compileJava {
  options.incremental = true
  options.fork = true
  options.failOnError = false
}
</syntaxhighlight>
For more details, see: {{Internal|Gradle JavaCompile Task Type#Overview|JavaCompile type}}
==<tt>compileTestJava</tt>==
The "compileTestJava" task compiles the sources managed by the [[#The_.22test.22_Source_Set|"test" source set]]. The task is backed by the [[Gradle JavaCompile Task Type#Overview|JavaCompile]] type, and can be used to change compilation options for test compilation. The syntax is similar to the one shown [[#compileJava|above]], just applied inside the "compileTestJava" script block.
==<tt>processResources</tt>==
The "processResources" task processes the [[#Resource_Files|resources]] managed by the [[#The_.22main.22_Source_Set|main source set]]. The task is an implementation of the Copy type. The task will automatically copy any files in src/main/resources to a directory that will be included in the project's JAR. This target directory will also be included in the runtime classpath of the tests. For more details see: {{Internal|Gradle_Copy_Task_Type#Overview|Copy task}}


===api===
==<tt>processTestResources</tt>==
The "processTestResources" task processes the [[#Resource_Files|resources]] managed by the [[#The_.22test.22_Source_Set|test source set]]. The task is an implementation of the Copy type. For more details see: {{Internal|Gradle_Copy_Task_Type#Overview|Copy task}}
==<span id='jar_Task'></span><tt>jar</tt>==
===Bytecode JAR===
Assembles the JAR file from the classes produced by the [[#The_.22main.22_Source_Set|"main" source set]] source files and "main" source set resources. No configuration is needed for a standard Java project. The task produces a single JAR conventionally named:
<''archiveBaseName''>[-''archiveAppendix'']<-''archiveVersion''>[-''archiveClassifier''].<''archiveExtension>
By default, that translates to:
<''project''>-<''version''>.jar
The JAR is placed in the build/libs project directory. It depends on the [[#classes|classes]] task.


This dependency configuration defines dependencies required to compile the production source of the project which ''are'' part of the API exposed by the project.
No task configuration is necessary by default, but the task can be configured in <code>build.gradle</code> using a <code>jar {...}</code> configuration block:
 
<syntaxhighlight lang='groovy'>
===compile===
jar {
  manifest.attributes 'Main-Class': 'playground.Main'
}
</syntaxhighlight>
For example, the name of the JAR can be changed through configuration, as explained in the [[#Custom_JAR_Name|Custom JAR Name]] section below. The task is backed by the [[Gradle_Jar_Task_Type#Overview|Jar]] type, and detailed configuration documentation is available in {{Internal|Gradle_Jar_Task_Type#Configuration|Jar Task Type}}
The plugin creates by default a "thin" JAR, which only includes the project classes. A "fat" JAR, or an uber-JAR, is a self-sufficient archive which contains both classes and dependencies needed to run an application. To create a "fat" JAR, see: {{Internal|Create_a_Fat_JAR_with_Gradle|Create a Fat JAR with Gradle}}
Note that [[Gradle Java Library Plugin|Java Library]] plugin integrates the "jar" task with the standard lifecycle task [[Gradle_Base_Plugin#assemble|assemble]].
Also see: {{Internal|Gradle_Artifacts#Artifact|Gradle Artifacts}}
====JAR Customizations====
=====Custom JAR Name=====
=====FAT JAR=====
{{Internal|Create_a_Fat_JAR_with_Gradle|Create a Fat JAR with Gradle}}


Deprecated, replaced by [[#implementation|implementation]].
===Source JAR===
<font color=darkgray>TODO</font>.


===implementation===
==<tt>javadoc</tt>==
Generates Javadoc for the [[#The_.22main.22_Source_Set|"main" source set]] classes.
==<tt>test</tt>==
The "test" task runs all the tests from the [[#The_.22test.22_Source_Set|"test" source set]] (src/test/java). Note that [[Gradle Java Library Plugin|Java Library]] plugin integrates the "test" task with the standard lifecycle task [[Gradle_Base_Plugin#check|check]]. For more details, see: {{Internal|Testing_with_Gradle_Java_Plugin#Overview|Testing with Gradle Java Plugin}}


This dependency configuration defines dependencies required to compile the production source of the project which ''are not'' part of the API exposed by the project.
==<tt>testClasses</tt>==
==<tt>classes</tt>==
==Lifecycle Tasks==
<font color=darkgray>Are these introduced by the Java plugin or they're also inherited?</font>
===<tt>buildDependents</tt>===


===compileOnly===
===<tt>buildNeeded</tt>===


===compileClasspath===
==Inherited Tasks==
The following tasks are lifecycle tasks inherited from the [[Gradle_Base_Plugin#Overview|Base]] plugin.
===<tt>assemble</tt>===
Standard lifecycle task, inherited from the [[Gradle_Base_Plugin#assemble|Base]] plugin. For the Java plugin, the 'assemble' task compiles the code and builds the JAR but does not run the tests. Other plugins, such as the [[Gradle War Plugin#Overview|War Plugin]], add more artifacts to this task. More details:{{Internal|Gradle_Base_Plugin#assemble|assemble}}


===annotationProcessor===
===<tt>build</tt>===
Standard lifecycle task: {{Internal|Gradle_Base_Plugin#build|build}}


===runtime===
===<tt>check</tt>===
 
Standard lifecycle task: {{Internal|Gradle_Base_Plugin#check|check}}
Deprecated by [[#api|api]] and [[#implementation|implementation]].
===<tt>clean</tt>===
 
{{Internal|Gradle_Base_Plugin#clean|clean}}
"runtime" has a special signification when it comes to [[Gradle_Artifact_Publishing_Concepts#Configuration|artifact publishing]]. It the project is used as a library, the "runtime" configuration is used to declare the artifacts of the library and their dependencies. The dependencies declared here are assumed to be the dependencies of the published artifact.
 
===runtimeOnly===
 
===runtimeClasspath===
 
===testCompile===
 
Deprecated.
 
===testImplementation===
 
This dependency configuration defines dependencies required to compile and run the test source of the project. For example the project decided to write test code with the test framework JUnit.
 
===testCompileOnly===
 
===testCompileClasspath===
 
===testRuntime===
 
Deprecated.
 
===testRuntimeOnly===
 
===testRuntimeClasspath===
 
===archives===
 
The "archives" configuration is the [[Gradle_Artifact_Publishing_Concepts#Configuration|standard configuration to assign artifacts to]]. The Java plugin automatically assigns the default jar to this configuration, as the only element. If a [[Gradle_Maven_Plugin#Overview|Maven plugin]] is present, it associates its "[[Gradle_Maven_Plugin#Overview|install]]" task with this configuration.
 
===default===


=Java Plugin Predefined Task Types=
==JavaCompile==
[[Gradle JavaCompile Task Type|JavaCompile]] exposed as "[[#compileJava|compileJava]]" task
==Jar==
[[Gradle Jar Task Type|Jar]] exposed as "[[#jar|jar]]" task
==JavaExec==
{{Internal|Gradle JavaExec Task Type|JavaExec}}
=Properties=
=Properties=
The Java plugin adds a number of [[Gradle_Project_Coordinates,_State_and_Configured_Properties#Overview|properties]] to your project. These properties have default values which are usually sufficient to get started.
====<tt>sourceCompatibility</tt>====
'sourceCompatibility' defines the language version of the source code. See [[#Use_a_Specific_Java_Version|Use a Specific Java Version]] below.
====<tt>targetCompatibility</tt>====
'targetCompatibility' defines the minimum JVM version the code should be run on (the version of the bytecode the compiler generates). See [[#Use_a_Specific_Java_Version|Use a Specific Java Version]] below.


The Java plugin adds a number of [[Gradle Properties#Overview|properties]] to your project. These properties have default values which are usually sufficient to get started.
=Customization=
Various aspects related to Java compilation are set in the "java" script block:
<syntaxhighlight lang='groovy'>
java {
  toolchain {
    languageVersion = JavaLanguageVersion.of(11)
  }
}
</syntaxhighlight>
==Use a Specific Java Version==
By default, Gradle will compile Java code to the language level of the JVM running Gradle. Since version 8, the Java compiler can be configured to produce bytecode for an older Java version, while making sure the code does not use any APIs from a more recent version.


===sourceCompatibility===
This can be changed with the usage of [[#Java_Toolchain|Java toolchains]].
<syntaxhighlight lang='groovy'>
java {
  toolchain {
    languageVersion = JavaLanguageVersion.of(11)
  }
}
</syntaxhighlight>
The level can be changed at task level:
<syntaxhighlight lang='groovy'>
compileJava {
  options.release = 11
}
</syntaxhighlight>


===targetCompatibility===
The legacy way to configure this is to set the "[[#sourceCompatibility|sourceCompatibility]]" and "[[#targetCompatibility|targetCompatibility]]" properties at the top level of build.gradle file:
<syntaxhighlight lang='groovy'>
sourceCompatibility = 15
targetCompatibility = 11
</syntaxhighlight>If the toolchain is used, that makes it illegal to use sourceCompatibility and targetCompatibility.


=<span id='Plugin_Tasks'></span>Tasks=
The target compatibility level reflects in the generated classes bytecode version. For more details, see: {{Internal|Java Bytecode Version|Java Bytecode Version}}


==Build Tasks==
==Compiler Options Customization==
 
Compiler options can be configured in the [[#compileJava|compileJava]] and [[#compileTestJava|compileTestJava]] tasks, as shown above.
===clean===
==Source Set Customization==
 
===Custom Source Directories===
Deletes the build directory, removing all built files.
The source directories for both main and test source sets can be reconfigured as follows (the example only shows main, test is similar):
 
<syntaxhighlight lang='groovy'>
===assemble===
sourceSets {
 
  main {
Compiles code and builds the JAR but does not run tests. Other plugins, such as the [[Gradle War Plugin#Overview|War Plugin]], add more artifacts to this task.
    java {
 
      srcDirs = ['src/somethingelse/java']
===build===
    }
 
  }
===jar===
}
 
</syntaxhighlight>
===compileJava===
To add directories, use this syntax:
 
<syntaxhighlight lang='groovy'>
===compileTestJava===
sourceSets {
 
  main {
===processResources===
    java {
 
      srcDir 'src/somethingelse/java'
===processTestResources===
    }
 
  }
===testClasses===
}
 
</syntaxhighlight>
==Verification Tasks==
or
 
<syntaxhighlight lang='groovy'>
===check===
sourceSets.main.java.srcDirs += ['src/somethingelse/java']
 
</syntaxhighlight>
Compiles and tests the code.
It is equivalent with:
 
<syntaxhighlight lang='groovy'>
==Documentation Tasks==
sourceSets {
  main {
    java {
      srcDirs = ['src/main/java', 'src/somethingelse/java']
    }
  }
}
</syntaxhighlight>
===Custom Resource Directories===
<syntaxhighlight lang='groovy'>
sourceSets {
  main {
    resources {
      srcDirs = ["src/main/resources", "src/main/configs"]
      excludes = ['**/something/**']
    }
  }
}
</syntaxhighlight>


===javadoc===
=Testing with Gradle Java Plugin=
{{Internal|Testing with Gradle Java Plugin#Overview|Testing with Gradle Java Plugin}}

Latest revision as of 19:12, 12 June 2021

External

Internal

Overview

The Java plugin adds Java compilation, testing and packaging capabilities to a project.

plugins {
  id 'java'
}

The Java plugin also serves as the basis for many of the other JVM language Gradle plugins. The Java plugin builds upon a Java Base plugin.

However, it is the Java Library plugin that should be used by default with Java projects instead of Java plugin. Java Library plugin extends the Java plugin, so it offers all the features of the Java plugin, plus a set of additional ones:

Java Library Plugin

The Java plugin instantiates by default two source sets ("main" and "test"). Each of these source sets has an associated compile task: compileJava (which is the abbreviation of "compileMainJava") for the "main" source set and compileTestJava for the "test" source set. To compile the production and test code:

The Java plugin also adds a jar task that assembles a JAR file with the classes produced from the "main" source set code.

The default configuration of the source sets is convention-based, borrowing the directory layout from Maven projects. As such, if those conventions are followed, generally not much needs to be added to the build script to get a useful build.

Concepts

Source Set

https://docs.gradle.org/current/dsl/org.gradle.api.tasks.SourceSet.html

A source set is a logical grouping of source files and resources, typically associated on the base of their purpose: application production code, test code, etc. Each source set contains sources and resources from typically one, but possibly more directories, which are listed as part of the source set. The files that form a source set don't have to be located in the same directory. The source set concept was introduced by the Java plugin. A source set directory has subdirectories for java sources, and other types of sources. The Java plugin instantiates by default two source sets: main and test. They correspond to the conventional directories from "src":

.
└─ src
   ├─ main                  ← source set "main"
   │    ├─ java             ← the java subtree of the "main" source set
   │    │    └─ playground
   │    │        └─ Sample.java
   │    └─ resources        ← the resource subtree of the "main" source set
   │
   └─ test                  ← source set "test"
        ├─ java             ← the java subtree of the "test" source set
        │    └─ playground
        │        └─ SampleTest.java
        └─ resources        ← the resource subtree of the "test" source set

Aside from the source files and resources, the source set also keeps track of various classpaths, including any dependencies, require the compile or run the code. It does that by maintaining a set of configurations corresponding to the compilation classpath, annotation processor classpath and runtime classpath. Each source set has associated an "<source-set-name>implementation" configuration. In case of the "main" source set, main is omitted and the configuration is named simply "implementation". Also see:

Configuration

Finally, the source set keeps track of where the compiled class files are placed, as a source set output.

The Java plugin automatically creates compilation tasks for each source set, naming them "compile<source-set-name>Java". In case of the "main" source set, the <source-set-name> is omitted and the task is called "compileJava".


SourceSet.png


Each source set is internally maintained in the runtime project hierarchy as child of the Java plugin. However, it can be configured via a top-level script blocks:

plugins {
  id 'java'
}
sourceSets {
  main {
    java {
      srcDirs = ['src/main/java']
    }
    resources {
      srcDirs = ['src/main/resources']
      excludes = ['**/something/**']
    }
  }
  test {
    java {
      srcDirs = ['src/test/java']
    }
    resources {
      srcDirs = ['src/test/resources']
      excludes = ['**/something/**']
    }
  }
}

More details on how to reconfigure existing source sets is available below in the section Source Set Customization.

Source Set Lifecycle

How is a source set configured during the project lifecycle? How are configurations injected?

Resource Files

Java projects typically include resource other than source files, such as property files, that may need processing - for example by replacing tokens within the files - and packaging them within the final JAR. Typical use cases for resource files are images, configuration files, localization data. The Java plugin handles this automatically by creating a dedicated task for each source set, called "process<source-set-name>Resources", or "processResources" for the main source set. The processing consists in copying files from src/<source-set>/resources to a directory that will be included in the project's JAR. This target directory will also be included in the runtime classpath of the tests.

Default Source Sets

The "main" Source Set

The main source set is conventionally associated with all source files found under src/main/java and all resource files from src/main/resources. The sources managed by the main source set are compiled by the compileJava task. The resources are processed by the processResources task. The main source set is associated with the "compileOnly", "runtimeOnly" and "implementation" configurations. The jar task packages the main source set compiled classes and resources.

└─ src
    └─ main
         ├─ java
         └─ resources

The "test" Source Set

The "test" source set is conventionally associated with all the source file under src/test/java. It contains test source code, which is compiled and executed using JUnit or TestNG. These are typically unit tests, but any test can be include in this source set as long as they all share the same compilation and runtime classpaths. The sources managed by the "test" source set are compiled by the compileTestJava task, and the tests are executed by the test task. The resources are processed by the processTestResources task. The test source set is associated with the "testCompileOnly", "testRuntimeOnly" and "testImplementation" configurations.

└─ src
    └─ test
         ├─ java
         └─ resources

Custom Source Set

New source sets can be defined, typically for one or both of the following reasons:

  • The source code should be keep separate from the existing source sets for aesthetics and manageability.
  • The source code requires a different, unique compilation or runtime classpaths.
  • The generated code should be handled differently than the code from main and test source set.

Java Toolchain

The toolchain options protect against problems with the project being built with different Java versions.

TODO: https://docs.gradle.org/current/userguide/toolchains.html.

Component

The plugin adds a "java" software component accessible via components.java. The JAR file produced by the jar task is the artifact associated with the Java component, and its dependencies are those of the runtime configuration.

Dependency Configurations

Default Configurations added by the Java Plugin

Tasks

compileJava

The "compileJava" task compiles the sources managed by the "main" source set. The task is backed by the JavaCompile type.

To change compiler options, configure the task as follows:

compileJava {
  options.incremental = true
  options.fork = true
  options.failOnError = false
}

For more details, see:

JavaCompile type

compileTestJava

The "compileTestJava" task compiles the sources managed by the "test" source set. The task is backed by the JavaCompile type, and can be used to change compilation options for test compilation. The syntax is similar to the one shown above, just applied inside the "compileTestJava" script block.

processResources

The "processResources" task processes the resources managed by the main source set. The task is an implementation of the Copy type. The task will automatically copy any files in src/main/resources to a directory that will be included in the project's JAR. This target directory will also be included in the runtime classpath of the tests. For more details see:

Copy task

processTestResources

The "processTestResources" task processes the resources managed by the test source set. The task is an implementation of the Copy type. For more details see:

Copy task

jar

Bytecode JAR

Assembles the JAR file from the classes produced by the "main" source set source files and "main" source set resources. No configuration is needed for a standard Java project. The task produces a single JAR conventionally named:

<archiveBaseName>[-archiveAppendix]<-archiveVersion>[-archiveClassifier].<archiveExtension>

By default, that translates to:

<project>-<version>.jar

The JAR is placed in the build/libs project directory. It depends on the classes task.

No task configuration is necessary by default, but the task can be configured in build.gradle using a jar {...} configuration block:

jar {
  manifest.attributes 'Main-Class': 'playground.Main'
}

For example, the name of the JAR can be changed through configuration, as explained in the Custom JAR Name section below. The task is backed by the Jar type, and detailed configuration documentation is available in

Jar Task Type

The plugin creates by default a "thin" JAR, which only includes the project classes. A "fat" JAR, or an uber-JAR, is a self-sufficient archive which contains both classes and dependencies needed to run an application. To create a "fat" JAR, see:

Create a Fat JAR with Gradle

Note that Java Library plugin integrates the "jar" task with the standard lifecycle task assemble.

Also see:

Gradle Artifacts

JAR Customizations

Custom JAR Name
FAT JAR
Create a Fat JAR with Gradle

Source JAR

TODO.

javadoc

Generates Javadoc for the "main" source set classes.

test

The "test" task runs all the tests from the "test" source set (src/test/java). Note that Java Library plugin integrates the "test" task with the standard lifecycle task check. For more details, see:

Testing with Gradle Java Plugin

testClasses

classes

Lifecycle Tasks

Are these introduced by the Java plugin or they're also inherited?

buildDependents

buildNeeded

Inherited Tasks

The following tasks are lifecycle tasks inherited from the Base plugin.

assemble

Standard lifecycle task, inherited from the Base plugin. For the Java plugin, the 'assemble' task compiles the code and builds the JAR but does not run the tests. Other plugins, such as the War Plugin, add more artifacts to this task. More details:

assemble

build

Standard lifecycle task:

build

check

Standard lifecycle task:

check

clean

clean

Java Plugin Predefined Task Types

JavaCompile

JavaCompile exposed as "compileJava" task

Jar

Jar exposed as "jar" task

JavaExec

JavaExec

Properties

The Java plugin adds a number of properties to your project. These properties have default values which are usually sufficient to get started.

sourceCompatibility

'sourceCompatibility' defines the language version of the source code. See Use a Specific Java Version below.

targetCompatibility

'targetCompatibility' defines the minimum JVM version the code should be run on (the version of the bytecode the compiler generates). See Use a Specific Java Version below.

Customization

Various aspects related to Java compilation are set in the "java" script block:

java {
  toolchain {
    languageVersion = JavaLanguageVersion.of(11)
  }
}

Use a Specific Java Version

By default, Gradle will compile Java code to the language level of the JVM running Gradle. Since version 8, the Java compiler can be configured to produce bytecode for an older Java version, while making sure the code does not use any APIs from a more recent version.

This can be changed with the usage of Java toolchains.

java {
  toolchain {
    languageVersion = JavaLanguageVersion.of(11)
  }
}

The level can be changed at task level:

compileJava {
  options.release = 11
}

The legacy way to configure this is to set the "sourceCompatibility" and "targetCompatibility" properties at the top level of build.gradle file:

sourceCompatibility = 15
targetCompatibility = 11

If the toolchain is used, that makes it illegal to use sourceCompatibility and targetCompatibility. The target compatibility level reflects in the generated classes bytecode version. For more details, see:

Java Bytecode Version

Compiler Options Customization

Compiler options can be configured in the compileJava and compileTestJava tasks, as shown above.

Source Set Customization

Custom Source Directories

The source directories for both main and test source sets can be reconfigured as follows (the example only shows main, test is similar):

sourceSets {
  main {
    java {
      srcDirs = ['src/somethingelse/java']
    }
  }
}

To add directories, use this syntax:

sourceSets {
  main {
    java {
      srcDir 'src/somethingelse/java'
    }
  }
}

or

sourceSets.main.java.srcDirs += ['src/somethingelse/java']

It is equivalent with:

sourceSets {
  main {
    java {
      srcDirs = ['src/main/java', 'src/somethingelse/java']
    }
  }
}

Custom Resource Directories

sourceSets {
  main {
    resources {
      srcDirs = ["src/main/resources", "src/main/configs"]
      excludes = ['**/something/**']
    }
  }
}

Testing with Gradle Java Plugin

Testing with Gradle Java Plugin