The Java plugin adds Java compilation along with testing and bundling capabilities to a project. It serves as the basis for many of the other Gradle plugins.
To use the Java plugin, include the following in your build script:
The Java plugin introduces the concept of a source set. A source set is simply a group of source files which are compiled and executed together. These source files may include Java source files and resource files. Other plugins add the ability to include Groovy and Scala source files in a source set. A source set has an associated compile classpath, and runtime classpath.
One use for source sets is to group source files into logical groups which describe their purpose. For example, you might use a source set to define an integration test suite, or you might use separate source sets to define the API and implementation classes of your project.
The Java plugin defines two standard source sets, called main
and test
.
The main
source set contains your production source code, which is compiled and assembled
into a JAR file. The test
source set contains your test source code, which is
compiled and executed using JUnit or TestNG. These can be unit tests, integration tests, acceptance tests,
or any combination that is useful to you.
The Java plugin adds a number of tasks to your project, as shown below.
Table 23.1. Java plugin - tasks
Task name | Depends on | Type | Description |
compileJava
|
All tasks which produce the compile classpath. This includes the jar task for
project dependencies included in the compile configuration.
|
JavaCompile |
Compiles production Java source files using javac. |
processResources
|
- | Copy |
Copies production resources into the production classes directory. |
classes
|
The compileJava task and the processResources task.
Some plugins add additional compilation tasks.
|
Task |
Assembles the production classes directory. |
compileTestJava
|
compile , plus all tasks which produce the test compile classpath.
|
JavaCompile |
Compiles test Java source files using javac. |
processTestResources
|
- | Copy |
Copies test resources into the test classes directory. |
testClasses
|
compileTestJava task and processTestResources task.
Some plugins add additional test compilation tasks.
|
Task |
Assembles the test classes directory. |
jar
|
compile
|
Jar |
Assembles the JAR file |
javadoc
|
compile |
Javadoc |
Generates API documentation for the production Java source, using Javadoc |
test
|
compile ,
compileTest ,
plus all tasks which produce the test runtime classpath.
|
Test |
Runs the unit tests using JUnit or TestNG. |
uploadArchives
|
The tasks which produce the artifacts in the archives configuration, including jar .
|
Upload |
Uploads artifacts in the archives configuration, including the JAR file. |
clean
|
- | Delete |
Deletes the project build directory. |
clean
|
- | Delete |
Deletes files created by specified task. cleanJar
will delete the JAR file created by the jar task, and
cleanTest will delete the test results created by the test task.
|
For each source set you add to the project, the Java plugin adds the following compilation tasks:
Table 23.2. Java plugin - source set tasks
Task name | Depends on | Type | Description |
compile
|
All tasks which produce the source set's compile classpath. | JavaCompile |
Compiles the given source set's Java source files using javac. |
process
|
- | Copy |
Copies the given source set's resources into the classes directory. |
|
The compile task and
the process task.
Some plugins add additional compilation tasks for the source set.
|
Task |
Assembles the given source set's classes directory. |
The Java plugin also adds a number of tasks which form a lifecycle for the project:
Table 23.3. Java plugin - lifecycle tasks
Task name | Depends on | Type | Description |
assemble
|
All archive tasks in the project, including jar . Some plugins add additional
archive tasks to the project.
|
Task |
Assembles all the archives in the project. |
check
|
All verification tasks in the project, including test . Some plugins add
additional verification tasks to the project.
|
Task |
Performs all verification tasks in the project. |
build
|
check and assemble
|
Task |
Performs a full build of the project. |
buildNeeded
|
build and buildNeeded tasks in all project lib dependencies of the
testRuntime configuration.
|
Task |
Performs a full build of the project and all projects it depends on. |
buildDependents
|
build and buildDependents tasks in all projects with a project lib
dependency on this project in a testRuntime configuration.
|
Task |
Performs a full build of the project and all projects which depend on it. |
build
|
The tasks which produce the artifacts in configuration ConfigName .
|
Task |
Assembles the artifacts in the specified configuration. The task is added by the Base plugin which is implicitly applied by the Java plugin. |
upload
|
The tasks which uploads the artifacts in configuration ConfigName .
|
Upload |
Assembles and uploads the artifacts in the specified configuration. The task is added by the Base plugin which is implicitly applied by the Java plugin. |
The following diagram shows the relationships between these tasks.
The Java plugin assumes the project layout shown below. None of these directories need exist or have anything in them. The Java plugin will compile whatever it finds, and handles anything which is missing.
Table 23.4. Java plugin - default project layout
Directory | Meaning | |
src/main/java
|
Production Java source | |
src/main/resources
|
Production resources | |
src/test/java
|
Test Java source | |
src/test/resources
|
Test resources | |
src/
|
Java source for the given source set | |
src/
|
Resources for the given source set |
You configure the project layout by configuring the appropriate source set. This is discussed in more detail in the following sections. Here is a brief example which changes the main Java and resource source directories.
Example 23.2. Custom Java source layout
build.gradle
sourceSets { main { java { srcDir 'src/java' } resources { srcDir 'src/resources' } } }
The Java plugin adds a number of dependency configurations to your project, as shown below. It assigns
those configurations to tasks such as compileJava
and test
.
Table 23.5. Java plugin - dependency configurations
Name | Extends | Used by tasks | Meaning |
compile | - | compileJava | Compile time dependencies |
runtime | compile | - | Runtime dependencies |
testCompile | compile | compileTestJava | Additional dependencies for compiling tests. |
testRuntime | runtime, testCompile | test | Additional dependencies for running tests only. |
archives | - | uploadArchives | Artifacts (e.g. jars) produced by this project. |
default | runtime | - | The default configuration used by a project dependency on this project. Contains the artifacts and dependencies required by this project at runtime. |
For each source set you add to the project, the Java plugins adds the following dependency configurations:
Table 23.6. Java plugin - source set dependency configurations
Name | Extends | Used by tasks | Meaning |
|
- | compile |
Compile time dependencies for the given source set |
|
|
- | Runtime dependencies for the given source set |
The Java plugin adds a number of convention properties to the project, shown below. You can use these properties in your build script as though they were properties of the project object (see Section 21.6, “Conventions”).
Table 23.7. Java plugin - directory properties
Property name | Type | Default value | Description |
reportsDirName
|
String
|
reports
|
The name of the directory to generate reports into, relative to the build directory. |
reportsDir
|
File (read-only)
|
|
The directory to generate reports into. |
testResultsDirName
|
String
|
test-results
|
The name of the directory to generate test result .xml files into, relative to the build directory. |
testResultsDir
|
File (read-only)
|
|
The directory to generate test result .xml files into. |
testReportDirName
|
String
|
tests
|
The name of the directory to generate the test report into, relative to the reports directory. |
testReportDir
|
File (read-only)
|
|
The directory to generate the test report into. |
libsDirName
|
String
|
libs
|
The name of the directory to generate libraries into, relative to the build directory. |
libsDir
|
File (read-only)
|
|
The directory to generate libraries into. |
distsDirName
|
String
|
distributions
|
The name of the directory to generate distributions into, relative to the build directory. |
distsDir
|
File (read-only)
|
|
The directory to generate distributions into. |
docsDirName
|
String
|
docs
|
The name of the directory to generate documentation into, relative to the build directory. |
docsDir
|
File (read-only)
|
|
The directory to generate documentation into. |
dependencyCacheDirName
|
String
|
dependency-cache
|
The name of the directory to use to cache source dependency information, relative to the build directory. |
dependencyCacheDir
|
File (read-only)
|
|
The directory to use to cache source dependency information. |
Table 23.8. Java plugin - other properties
Property name | Type | Default value | Description |
sourceSets
|
SourceSetContainer (read-only) |
Not null | Contains the project's source sets. |
sourceCompatibility
|
JavaVersion . Can also set using a String or a Number, e.g.
'1.5' or 1.5 .
|
version of the current JVM in use | Java version compatibility to use when compiling Java source. |
targetCompatibility
|
JavaVersion . Can also set using a String or Number, e.g.
'1.5' or 1.5 .
|
|
Java version to generate classes for. |
archivesBaseName
|
String
|
|
The basename to use for archives, such as JAR or ZIP files. |
manifest
|
Manifest |
an empty manifest | The manifest to include in all JAR files. |
These properties are provided by convention objects of type JavaPluginConvention
,
and BasePluginConvention
.
You can access the source sets of a project using the sourceSets
property. This
is a container for the project's source sets, of type SourceSetContainer
.
There is also a sourceSets { }
script block, which you can pass a closure to configure the
source set container. The source set container works pretty much the same way as other containers, such
as tasks
.
Example 23.3. Accessing a source set
build.gradle
// Various ways to access the main source set println sourceSets.main.output.classesDir println sourceSets['main'].output.classesDir sourceSets { println main.output.classesDir } sourceSets { main { println output.classesDir } } // Iterate over the source sets sourceSets.all { println name }
To configure an existing source set, you simply use one of the above access methods to set the properties of the source set. The properties are described below. Here is an example which configures the main Java and resources directories:
Example 23.4. Configuring the source directories of a source set
build.gradle
sourceSets { main { java { srcDir 'src/java' } resources { srcDir 'src/resources' } } }
The following table lists some of the important properties of a source set.
You can find more details in the API documentation for SourceSet
.
Table 23.9. Java plugin - source set properties
Property name | Type | Default value | Description |
name
|
String (read-only)
|
Not null | The name of the source set, used to identify it. |
output
|
SourceSetOutput (read-only)
|
Not null | The output files of the source set, containing its compiled classes and resources. |
output.classesDir
|
File
|
|
The directory to generate the classes of this source set into. |
output.resourcesDir
|
File
|
|
The directory to generate the resources of this source set into. |
compileClasspath
|
FileCollection
|
compile configuration.
|
The classpath to use when compiling the source files of this source set. |
runtimeClasspath
|
FileCollection
|
output + runtime configuration.
|
The classpath to use when executing the classes of this source set. |
java
|
SourceDirectorySet (read-only)
|
Not null |
The Java source files of this source set. Contains only .java files
found in the Java source directories, and excludes all other files.
|
java.srcDirs
|
Set<File> . Can set using anything described in Section 16.5, “Specifying a set of input files”.
|
[
|
The source directories containing the Java source files of this source set. |
resources
|
SourceDirectorySet (read-only)
|
Not null |
The resources of this source set. Contains only resources, and excludes any
.java files found in the resource source directories. Other plugins,
such as the Groovy plugin, exclude additional types of files from this collection.
|
resources.srcDirs
|
Set<File> . Can set using anything described in Section 16.5, “Specifying a set of input files”.
|
[
|
The source directories containing the resources of this source set. |
allJava
|
SourceDirectorySet (read-only)
|
java
|
All .java files of this source set. Some plugins, such as the Groovy plugin,
add additional Java source files to this collection.
|
allSource
|
SourceDirectorySet (read-only)
|
resources + java
|
All source files of this source set. This include all resource files and all Java source files. Some plugins, such as the Groovy plugin, add additional source files to this collection. |
To define a new source set, you simply reference it in the sourceSets { }
block. Here's an example:
When you define a new source set, the Java plugin adds some dependency configurations for the source set, as shown in Table 23.6, “Java plugin - source set dependency configurations”. You can use these configurations to define the compile and runtime dependencies of the source set.
Example 23.6. Defining source set dependencies
build.gradle
sourceSets { intTest } dependencies { intTestCompile 'junit:junit:4.11' intTestRuntime 'org.ow2.asm:asm-all:4.0' }
The Java plugin also adds a number of tasks which assemble the classes for the
source set, as shown in Table 23.2, “Java plugin - source set tasks”. For example, for a source set called
intTest
, compiling the classes for this source set is done by
running gradle intTestClasses
.
Example 23.7. Compiling a source set
Output of gradle intTestClasses
> gradle intTestClasses :compileIntTestJava :processIntTestResources :intTestClasses BUILD SUCCESSFUL Total time: 1 secs
Adding a JAR containing the classes of a source set:
Example 23.8. Assembling a JAR for a source set
build.gradle
task intTestJar(type: Jar) { from sourceSets.intTest.output }
Generating Javadoc for a source set:
Example 23.9. Generating the Javadoc for a source set
build.gradle
task intTestJavadoc(type: Javadoc) { source sourceSets.intTest.allJava }
Adding a test suite to run the tests in a source set:
Example 23.10. Running tests in a source set
build.gradle
task intTest(type: Test) { testClassesDir = sourceSets.intTest.output.classesDir classpath = sourceSets.intTest.runtimeClasspath }
The javadoc
task is an instance of Javadoc
.
It supports the core javadoc options and the options of the standard doclet described in the
reference documentation
of the Javadoc executable.
For a complete list of supported Javadoc options consult the API documentation of the following classes:
CoreJavadocOptions
and StandardJavadocDocletOptions
.
Table 23.10. Java plugin - Javadoc properties
Task Property | Type | Default Value |
classpath
|
FileCollection |
sourceSets.main.output + sourceSets.main.compileClasspath |
source |
FileTree . Can set using anything described in Section 16.5, “Specifying a set of input files”. |
sourceSets.main.allJava |
destinationDir
|
File |
|
title
|
String |
The name and version of the project |
The clean
task is an instance of Delete
. It
simply removes the directory denoted by its dir
property.
Table 23.11. Java plugin - Clean properties
Task Property | Type | Default Value |
dir
|
File |
|
The Java plugin uses the Copy
task for resource handling. It adds an
instance for each source set in the project. You can find out more about the copy task in
Section 16.6, “Copying files”.
Table 23.12. Java plugin - ProcessResources properties
Task Property | Type | Default Value |
srcDirs
|
Object . Can set using anything described in Section 16.5, “Specifying a set of input files”. |
|
destinationDir
|
File . Can set using anything described in Section 16.1, “Locating files”. |
|
The Java plugin adds a JavaCompile
instance for each
source set in the project. Some of the most common configuration options are shown below.
Table 23.13. Java plugin - Compile properties
Task Property | Type | Default Value |
classpath
|
FileCollection |
|
source
|
FileTree . Can set using anything described in Section 16.5, “Specifying a set of input files”. |
|
destinationDir
|
File . |
|
By default, the Java compiler runs in the Gradle process. Setting options.fork
to true
causes compilation to occur in a separate process. In the case of the Ant javac task, this means that a new process will be
forked for each compile task, which can slow down compilation. Conversely, Gradle's direct compiler integration (see above) will
reuse the same compiler process as much as possible. In both cases, all fork options specified
with options.forkOptions
will be honored.
Starting with Gradle 2.1, it is possible to compile java incrementally. This feature is still incubating.
See the JavaCompile
task for information on how to enable it.
Main goals for incremental compilations are:
The incremental compilation at a high level:
The test
task is an instance of Test
.
It automatically detects and executes all unit tests in the test
source set.
It also generates a report once test execution is complete. JUnit and TestNG are both supported.
Have a look at Test
for the complete API.
Tests are executed in a separate JVM, isolated from the main build process. The Test
task's
API allows you some control over how this happens.
There are a number of properties which control how the test process is launched. This includes things such as system properties, JVM arguments, and the Java executable to use.
You can specify whether or not to execute your tests in parallel. Gradle provides parallel test execution
by running multiple test processes concurrently. Each test process executes only a single test at a time, so you
generally don't need to do anything special to your tests to take advantage of this.
The maxParallelForks
property specifies the maximum number of test processes to run
at any given time. The default is 1, that is, do not execute the tests in parallel.
The test process sets the org.gradle.test.worker
system property to a unique
identifier for that test process, which you can use, for example, in files names or other
resource identifiers.
You can specify that test processes should be restarted after it has executed a certain number of
test classes. This can be a useful alternative to giving your test process a very large
heap.
The forkEvery
property specifies the
maximum number of test classes to execute in a test process. The default is to execute an unlimited number
of tests in each test process.
The task has an ignoreFailures
property to control the behavior when tests fail.
The Test
task always executes every test that it detects. It stops the build afterwards if ignoreFailures
is false and there are failing tests. The default value of ignoreFailures
is false.
The testLogging
property allows you to configure which test events are going to be logged and at
which detail level. By default, a concise message will be logged for every failed test. See
TestLoggingContainer
for how to tune test logging to your
preferences.
The test task provides a Test.getDebug()
property that can be set to launch to make the JVM wait for a
debugger to attach to port 5005 before proceeding with test execution.
This can also be enabled at invocation time via the --debug-jvm
task option.
Starting with Gradle 1.10, it is possible to include only specific tests, based on the test name pattern.
Filtering is a different mechanism than test class inclusion / exclusion that will be described in the next few paragraphs
(-Dtest.single
, test.include
and friends).
The latter is based on files, e.g. the physical location of the test implementation class.
File-level test selection does not support many interesting scenarios that are possible with test-level filtering.
Some of them Gradle handles now and some will be satisfied in future releases:
Test filtering feature has following characteristic:
Example 23.11. Filtering tests in the build script
build.gradle
test { filter { //include specific method in any of the tests includeTestsMatching "*UiCheck" //include all tests from package includeTestsMatching "org.gradle.internal.*" //include all integration tests includeTestsMatching "*IntegTest" } }
For more details and examples please see the TestFilter
reference.
Some examples of using the command line option:
gradle test --tests org.gradle.SomeTest.someSpecificFeature
gradle test --tests *SomeTest.someSpecificFeature
gradle test --tests *SomeSpecificTest
gradle test --tests all.in.specific.package*
gradle test --tests *IntegTest
gradle test --tests *IntegTest*ui*
gradle someTestTask --tests *UiTest someOtherTestTask --tests *WebTest*ui
Setting a system property of taskName.single
= testNamePattern
will only execute tests that match the specified testNamePattern
.
The taskName
can be a full multi-project path like “:sub1:sub2:test”
or just the task name. The testNamePattern
will be used to form an include
pattern of “**/testNamePattern*.class”;.
If no tests with this pattern can be found an exception is thrown. This is to shield you from false security.
If tests of more than one subproject are executed, the pattern is applied to each subproject. An exception
is thrown if no tests can be found for a particular subproject. In such a case you can use the path notation of the
pattern, so that the pattern is applied only to the test task of a specific subproject. Alternatively you can specify the fully
qualified task name to be executed. You can also specify multiple patterns. Examples:
gradle -Dtest.single=ThisUniquelyNamedTest test
gradle -Dtest.single=a/b/ test
gradle -DintegTest.single=*IntegrationTest integTest
gradle -Dtest.single=:proj1:test:Customer build
gradle -DintegTest.single=c/d/ :proj1:integTest
The Test
task detects which classes are test classes by inspecting the compiled test classes.
By default it scans all .class
files. You can set custom includes / excludes, only those
classes will be scanned. Depending on the test framework used (JUnit / TestNG) the test class detection
uses different criteria.
When using JUnit, we scan for both JUnit 3 and 4 test classes. If any of the following criteria match, the class is considered to be a JUnit test class:
Class or a super class extends TestCase
or GroovyTestCase
Class or a super class is annotated with @RunWith
Class or a super class contain a method annotated with @Test
When using TestNG, we scan for methods annotated with @Test
.
Note that abstract classes are not executed. Gradle also scans up the inheritance tree into jar files on the test classpath.
If you don't want to use test class detection, you can disable it by setting
scanForTestClasses
to false. This will make the test task only use includes /
excludes to find test classes. If scanForTestClasses
is false and no include
/ exclude patterns are specified, the defaults are
“**/*Tests.class
”, “**/*Test.class
” and
“**/Abstract*.class
” for include and exclude, respectively.
JUnit and TestNG allows sophisticated groupings of test methods.
For grouping JUnit test classes and methods JUnit 4.8 introduces the concept of categories.
[9]
The test
task allows the specification of the JUnit categories you want to include and exclude.
Example 23.12. JUnit Categories
build.gradle
test { useJUnit { includeCategories 'org.gradle.junit.CategoryA' excludeCategories 'org.gradle.junit.CategoryB' } }
The TestNG framework has a quite similar concept. In TestNG you can specify different test groups. [10] The test groups that should be included or excluded from the test execution can be configured in the test task.
Example 23.13. Grouping TestNG tests
build.gradle
test { useTestNG { excludeGroups 'integrationTests' includeGroups 'unitTests' } }
The Test
task generates the following results by default.
An HTML test report.
The results in an XML format that is compatible with the Ant JUnit report task. This format is supported by many other tools, such as CI servers.
Results in an efficient binary format. The task generates the other results from these binary results.
There is also a stand-alone TestReport
task type which can generate the HTML test
report from the binary results generated by one or more Test
task instances. To use this task type, you need
to define a destinationDir
and the test results to include in the report. Here is a sample which generates a
combined report for the unit tests from subprojects:
Example 23.14. Creating a unit test report for subprojects
build.gradle
subprojects { apply plugin: 'java' // Disable the test report for the individual test task test { reports.html.enabled = false } } task testReport(type: TestReport) { destinationDir = file("$buildDir/reports/allTests") // Include the results from the `test` task in all subprojects reportOn subprojects*.test }
You should note that the TestReport
type combines the results from multiple test
tasks and needs to aggregate the results of individual test classes. This means that if a given test class is executed by
multiple test tasks, then the test report will include executions of that class, but it can be hard to distinguish individual
executions of that class and their output.
TestNG supports parameterizing test methods, allowing a particular test method to be executed multiple times with different inputs. Gradle includes the parameter values in its reporting of the test method execution.
Given a parameterized test method named aTestMethod
that takes two parameters, it will be reported with the name:
aTestMethod(toStringValueOfParam1, toStringValueOfParam2)
. This makes identifying the parameter values for a
particular iteration easy.
Table 23.14. Java plugin - test properties
Task Property | Type | Default Value |
testClassesDir |
File |
sourceSets.test.output.classesDir |
classpath |
FileCollection |
sourceSets.test.runtimeClasspath |
testResultsDir |
File |
testResultsDir |
testReportDir |
File |
testReportDir |
testSrcDirs |
List<File> |
sourceSets.test.java.srcDirs |
The jar
task creates a JAR file containing the class files and resources of the
project. The JAR file is declared as an artifact in the archives
dependency
configuration. This means that the JAR is available in the classpath of a dependent project. If you upload
your project into a repository, this JAR is declared as part of the dependency descriptor. You can learn
more about how to work with archives in Section 16.8, “Creating archives” and artifact configurations in
Chapter 52, Publishing artifacts.
Each jar or war object has a manifest
property with a separate instance of Manifest
.
When the archive is generated, a corresponding MANIFEST.MF
file is written into the
archive.
Example 23.15. Customization of MANIFEST.MF
build.gradle
jar { manifest { attributes("Implementation-Title": "Gradle", "Implementation-Version": version) } }
You can create stand alone instances of a Manifest
. You can use that for example,
to share manifest information between jars.
Example 23.16. Creating a manifest object.
build.gradle
ext.sharedManifest = manifest { attributes("Implementation-Title": "Gradle", "Implementation-Version": version) } task fooJar(type: Jar) { manifest = project.manifest { from sharedManifest } }
You can merge other manifests into any Manifest
object. The other manifests might
be either described by a file path or, like in the example above, by a reference to another Manifest
object.
Example 23.17. Separate MANIFEST.MF for a particular archive
build.gradle
task barJar(type: Jar) { manifest { attributes key1: 'value1' from sharedManifest, 'src/config/basemanifest.txt' from('src/config/javabasemanifest.txt', 'src/config/libbasemanifest.txt') { eachEntry { details -> if (details.baseValue != details.mergeValue) { details.value = baseValue } if (details.key == 'foo') { details.exclude() } } } } }
Manifests are merged in the order they are declared by the from
statement. If
the base manifest and the merged manifest both define values for the same key, the merged manifest wins by default.
You can fully customize the merge behavior by adding eachEntry
actions in which
you have access to a ManifestMergeDetails
instance for each entry
of the resulting manifest. The merge is not immediately triggered by the from statement. It is done lazily,
either when generating the jar, or by calling writeTo
or effectiveManifest
You can easily write a manifest to disk.
Example 23.18. Separate MANIFEST.MF for a particular archive
build.gradle
jar.manifest.writeTo("$buildDir/mymanifest.mf")
How to upload your archives is described in Chapter 52, Publishing artifacts.
[9] The JUnit wiki contains a detailed description on how to work with JUnit categories: https://github.com/junit-team/junit/wiki/Categories.
[10] The TestNG documentation contains more details about test groups: http://testng.org/doc/documentation-main.html#test-groups.