Chapter 9
The Java Plugin

Table 9.1 shows the default project layout assumed by the Java Plugin. This is configurable via the convention object. Table 9.2 shows the tasks added by the Java Plugin. These tasks constitute a lifecycle for Java builds. Table 9.3 and Table 9.5 shows the most important properties of the convention object of the Java plugin.1 Gradle’s conventions contain a convention for the directory hierarchy as well as conventions for the element names of the hierarchy. For example the srcDirs are relative to the srcRoot. Therefore srcDirs is a read-only property. If you want to change the name of the source dirs you need to do this via the srcDirNames property. But the paths you specify here are relative to the srcRoot. This has the advantage to make bulk changes easy. If you change srcRoot from src to source, this automatically applies to all directory properties which are relative to srcRoot. As this also introduces an inflexibility, we have additional floating dirs, which are not bound to any hierarchy (see Table 9.4). For example code generation tool could make use of this, by adding a source dir which is located in the build folder.




Folder Meaning


src/main/java Application/Library sources


src/main/resources Application/Library resources


src/main/webapp Web application sources


src/test/java Test sources


src/test/resources Test resources



Table 9.1: Default Directory Layout





Taskname dependsOn Type



clean - org.gradle.api.tasks.Clean



javadoc - org.gradle.api.tasks.Javadoc



init - org.gradle.api.tasks.DefaultTask



resources initialize org.gradle.api.tasks.Resources



compile resources org.gradle.api.tasks.compile.Compile



testResources compile org.gradle.api.tasks.Resources



testCompile testResources org.gradle.api.tasks.compile.Compile



test testCompile org.gradle.api.tasks.testing.Test



libs test org.gradle.api.tasks.bundling.Bundle



uploadLibs libs org.gradle.api.tasks.Upload



dists uploadLibs org.gradle.api.tasks.bundling.Bundle



uploadDists dists org.gradle.api.tasks.Upload




Table 9.2: Java Plugin Tasks






Dir Name Dir File Default Value Name Default Value File




srcRootName srcRoot src projectDir/src




srcDirNames srcDirs main/java [srcRoot/main/java]




resourceDirNames resourceDirs main/resources [srcRoot/main/resources]




testSrcDirNames testSrcDirs test/java [srcRoot/test/java]




testResourceDirNames testResourceDirs main/resources [srcRoot/main/resources]




srcDocsDirName srcDocsDir docs srcRoot/docs




classesDirName classesDir classes buildDir/classes




testClassesDirName testClassesDir test-classes buildDir/test-classes




testResultsDir testResultsDirName test-results buildDir/test-results




distsDirName distsDir dists buildDir/dists




docsDirName docsDir docs buildDir/docs




javadocDirName javadocDir javadoc buildDir/javadoc





Table 9.3: Java Convention Object - Directory Hierarchy Properties





Property Type Default Value



floatingSrcDirs List empty



floatingResourceDirs List empty



floatingTestResourceDirs List empty



floatingTestResourceDirs List empty




Table 9.4: Java Convention Object - Floating Dir Properties





Property Type Default Value



sourceCompatibility String null



targetCompatibility String null



manifest GradleManifest empty



metaInf List empty




Table 9.5: Java Convention Object - Non Dir Properties

9.1 Init

The init task has no default action attached to it. It is meant to be a hook. You can add actions to it or associates your custom tasks with it. The Java Plugin executes this task before any other of its tasks get executed (except clean and javadoc which does not depends on init).

9.2 Javadoc

The javadoc task has no default association with any other task. It has no prerequisites on the actions of other tasks, as it operates on the source. It does not provide a fine-grained configuration API yet. If you need this, you have to use for example Ant’s javadoc task directly.



Convention to Property Mapping


Task Property Convention Property


srcDirs srcDirs


destinationDir [javadocDir]


9.3 Clean

The clean task simply removes the directory denoted by its dir property. This property is mapped to the buildDir property of the project. In future releases there will be more control of what gets deleted. If you need more control now, you can use the Ant delete task.

9.4 Resources

The Resources task has two instances, resources and testResources.




Convention to Property Mapping



Task Instance Task Property Convention Property



resources sourceDirs resourceDirs



resources destinationDir classesDir



testResources sourceDirs testResourceDirs



testResources destinationDir testClassesDir



The resources task offers includes and excludes directives as well as filters. Have a look at org.gradle.api.tasks.Resources to learn about the details.

9.5 Compile

The Compile task has two instances, compile and testCompile.




Convention to Property Mapping



Task Instance Task Property Convention Property



compile srcDirs srcDirs



compile destinationDir classesDir



compile sourceCompatibility sourceCompatibility



compile targetCompatibility targetCompatibility



testCompile srcDirs testSrcDirs



testCompile destinationDir testClassesDir



testCompile sourceCompatibility sourceCompatibility



testCompile targetCompatibility targetCompatibility



The classpath of the compile task is derived from two sources. One is the configuration assigned to the task by the dependency manager. The other classpath source is the unmanagedClasspath property: a list of files denoting a jar or a directory. Usually you create your classpath with the dependency manager. The unmanagedClasspath is used internally by Gradle. This classpath is not shared between projects in a multi-project build. Nor is it part of a dependency descriptor if you choose to upload your library to a repository. See section ?? how the JavaPlugin glues the tasks with the dependency manager and see the whole chapter 12 how to use the dependency manager.

Have a look at org.gradle.api.tasks.compile.Compile to learn about the details. The compile task delegates to Ants javac task to do the compile. Via the compile task you can set most of the properties of Ants javac task.

9.6 Test

The test task executes the unit tests which have been compiled by the testCompile task.



Convention to Property Mapping


Task Property Convention Property


testClassesDir testClassesDir


testResultsDir testResultsDir


unmanagedClasspath [classesDir]


Have a look at org.gradle.api.tasks.testing.Test to learn more. Right now the test results are always in XML-format. The task has a stopAtFailuresOrErrors property to control the behavior when tests are failing. The task always executes all the tests and afterwards stops the build if this property is true and there are failing tests or tests that have thrown an uncaught exception. The test task delegates to Ants junit task. TestNG is not supported yet. You can expect TestNG support with our next release.

9.7 Bundles

The Bundle task has two instances, libs and dists. The Bundle task is a special animal. It is a container for archive tasks (jar, zip, ...).




Convention to Property Mapping



Task Instance Task Property Convention Property



libs tasksBaseName project.archivesBaseName



dists tasksBaseName project.archivesBaseName



9.7.1 The libs Task

The libs task contains all the archive tasks which constitute the libraries needed to use your project as a library. Executing the libs task leads to the execution of all the contained archive tasks. In a multi-project build the archives which are produced by the libs task are available in the classpath of a dependent project. If you upload your project into a repository, those archives are part of the dependency descriptor. If you come from Maven you can have only one library jar per project. With Ivy you can have as many as you want. The Java plugin adds by default one jar archive to the libs task. The task name is by default projectName_jar and can of course be manipulated by this name. This jar contains the content of the classesDir. This is the behavior your are used from Maven. If you are happy with that you usually don’t have to touch this task. Except if you want to change the names of the generated archives.

The libs task depends on the test task and its archive tasks. The archive tasks assigned to the libs task depend by default on the test task as well. You can change this via the childrenDependsOn property of the libs task.

9.7.2 The dists Task

The dists task contains all the archive task that make up your distributions. For example a binary and a source distribution. The dists task has two purposes. One is providing a hook for distributions in the lifecycle. The other is for uploading distribution archives (the same is also true for the libs task.) The dists task depends on its archive tasks and the libs task. The contained archive tasks depend by default on the libs task as well. You can change this via the childrenDependsOn property of the dists task.

9.7.3 Adding Archives

The Bundle task has a couple of convenience methods for adding new archive tasks to it. Right now there are the methods (jar, war, zip, tar, tarGz, tarBzip2). They all behave in the same way.

  usePlugin('java')
  archivesBaseName = gradle // defaults to project.name
  version = 1.0
  dists {
      zip() {
          fileSet(dir: 'somedir')
      }
  }
  gradle_zip.baseName = 'i_am_special' // Now the generated archive will be: i_am_special-1.0.zip

This adds an archive task with the name gradle_zip. It is important to distinguish between the name of the archive task and the name of the archive generated by the archive task. The latter can be changed at any time later on and is by default gradle-1.0.zip. You can pass a closure to the zip() method, which statements are applied against the newly created archive task object. In section 9.8 you will learn more about which statements you can apply against a particular archive task.

  dists {
      zip(baseName: 'craidle', classifier: 'src') {
          fileSet(dir: 'somedir')
      }
  }

You can pass also optionally pass arguments to the zip() method. In this example we create an archive task with the name craidle_src_zip which generates an archive with the name craidle-1.0-src.zip.

9.8 Archive Tasks

An archive task is a task which produces an archive at execution time. The following archives tasks are available:




Type Accepted file container Extends



org.gradle.api.tasks.bundling.Zip fileSet, fileCollection, zipFileSet AbstractArchiveTask



org.gradle.api.tasks.bundling.Tar fileSet, fileCollection, zipFileSet, tarFileSet Zip



org.gradle.api.tasks.bundling.Jar fileSet, fileCollection, zipFileSet Zip



org.gradle.api.tasks.bundling.War fileSet, fileCollection, zipFileSet Jar



The following file containers are available:




Type

Meaning



org.gradle.api.tasks.util.FileSet

A set of files defined by a common baseDir and include/exclude patterns.



org.gradle.api.tasks.util.ZipFileSet

Extends FileSet with additional properties known from Ants zipfileset task.



org.gradle.api.tasks.util.TarFileSet

Extends ZipFileSet with additional properties known from Ants tarfileset task.



org.gradle.api.tasks.util.FileCollection

An arbitrary collection of files to the archive. In contrast to a FileSet they don’t need to have a common basedir.



org.gradle.api.tasks.util.AntDirective

An arbitrary Ant resource declaration.




Table 9.6: Filecontainer for Archives

To learn about all the details have a look at the javadoc of the archive task class or the file container class itself.

9.8.1 Common Properties

The name of the generated archive is assembled from the task properties baseName, classifier and extension to: baseName-project.version-classifier.extension.2 . The assembled name is accessible via the archiveName property. The name property denotes the name of the task, not the generated archive. An archive task has also a customName property. If this property is set, the archiveName property returns its value instead of assembling a name out of the properties mentioned above.

Archives have a destinationDir property to specify where the generated archive should be placed. It has also an archivePath property, which returns a File object with the absolute path of the generated archive.

9.8.2 Adding Content

To add content to an archive you must add file container to an archive (see Table 9.6). You can add as many file container as you like. They behave pretty much the same as the Ant resources with similar names.

  myZipTask.fileSet(dir: 'contentDir') {
   include('**/*.txt')
   exclude('**/*.gif')
  }

You can add arbitrary files to an archive:

  myZipTask.files('path_to_file1', 'path_to_file2')

Other examples:

  myZipTask.zipFileSet(dir: 'contentDir') {
   include('**/*.txt')
   exclude('**/*.gif')
   prefix = 'myprefix'
  }

  myTarTask.tarFileSet(dir: 'contentDir') {
   include('**/*.txt')
   exclude('**/*.gif')
   uid = 'myuid'
  }

There is also the option to add an arbitrary Ant expression describing an Ant resource.

  myZipTask.antDirective {
     zipgroupfileset(dir: new File(rootDir, 'lib'))
  }

This is for rather exotic use cases. Usually you should be fine with the file container provided by Gradle.

9.8.3 Merging

If you want to merge the content of other archives into the archive to be generated Gradle offers you two methods. One is merge:

  myZipTask.merge('path1/otherArchive1.zip', 'path2/otherArchive.tar.gz')

This merges the whole content of the archive passed to the merge method into the generated archive. If you need more control which content of the archive should be merged and to what path, you can pass a closure to the merge method:

  myZipTask.merge('path1/otherArchive1.zip', 'path2/otherArchive.tar.gz') {
   include('**/*.txt')
   exclude('**/*.gif')
   prefix = 'myprefix'
  }

Under the hood Gradle scans the extension of the archives to be merged. According to the extension, it creates a ZipFileSet or TarFileSet. The closure is applied to this newly created file container.
There is another method for merging called mergeGroup.

  myZipTask.mergeGroup('path_to_dir_with_archives') {
   include('**/*.zip')
   exclude('**/*.tar.gz')
  }

With this method you can assign a set of archives to be merged. Those archives have to be located under the directory you pass as an argument. You can define filters what archives should be included. They are always included fully and you can’t specify a path. If you need this features, you must use the merge method.

9.8.4 Manifest

The convention object of the JavaPlugin has a manifest property pointing to an instance of org.gradle.api.bundling.GradleManifest. With this GradleManifest object you can define the content of the MANIFEST.MF file of all the jar or a war archives in your project.

  manifest.mainAttributes(Implementation-Title: "Gradle", Implementation-Version: $version)

You can also define sections of a manifest file.

If a particular archive needs unique entries in its manifest you have to create an own GradleManifest object for it.

  manifest.mainAttributes(Implementation-Title: "Gradle", Implementation-Version: $version)
  myZipTask.manifest = new GradleManifest(manifest)
  myZipTask.manifest.mainAttributes(mykey: "myvalue")

Passing the common manifest object to the constructor of GradleManifest add the common manifest values to the task specific manifest instance.

9.8.5 MetaInf

The convention object of the JavaPlugin has a metaInf property pointing to a list of FileSet objects. With this file sets you can define which files should be in the META-INF directory of a jar or a war archive.

  metaInf << new FileSet(someDir)

9.9 Upload

The Upload task has two instances, uploadLibs and uploadDists. An easy way of describing there behavior, is that all archives added to the libs and dists bundle are uploaded by the corresponding upload task. An upload task uploads to the repositories assigned to it. If needed you have more control on what files get uploaded. Have a look at org.gradle.api.tasks.Upload to learn more.