The Java plugin

In Chapter 1, Getting Started with Gradle, we already created a Java project called FirstGradleProject. However, the discussion was only limited to the Eclipse plugin tasks. We did not discuss anything about the Java plugin. The Java plugin is part of the Gradle core API, which enables us to build a Java project with supporting tasks such as compiling the Java code, testing the code, assembling binaries to create libraries, and more. It supports conventions over configuration. This means, if we use this plugin, some default configuration is already available to the developer, such as the location of the source code, the location of the compiled class file, and the jar naming convention. Unless we want to override these configurations, we do not need to write a lot of code to work with the default tasks and properties.

To apply the Java plugin, we add a single statement to the build file:

apply plugin: 'java'

Internally, the apply method of the Java plugin is invoked with the project object as the argument and the build script is enabled in order to use all the tasks and properties provided by the Java plugin. To understand the Java plugin, we will create a new Java application (project name Ch04-Java1) similar to the Java project FirstGradleProject, which we developed in Chapter 1, Getting Started with Gradle. We will add two new classes, Customer and Order; we will also add a new JUnit or TestNG library dependency to support unit testing functionality for the project.

With the help of this example, we will explore different Java plugin conventions. To be precise, we will try to understand how different tasks work and which default conventions are supported by the Java plugin. Then, in the next section, we will learn how to customize different properties, so that we can create our own configuration in the build file.

Conventions

To understand conventions, let us start with the Java plugin tasks. Once we have applied the Java plugin to display all the available tasks in the project (project name Ch04-Java1), we can use the tasks command:

$ gradle tasks --all
...

Build tasks
-----------
assemble - Assembles the outputs of this project. [jar]
build - Assembles and tests this project. [assemble, check]
buildDependents - Assembles and tests this project and all projects that depend on it. [build]
buildNeeded - Assembles and tests this project and all projects it depends on. [build]
classes - Assembles classes 'main'.
  compileJava - Compiles Java source 'main:java'.
  processResources - Processes JVM resources 'main:resources'.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes. [classes]
testClasses - Assembles classes 'test'. [classes]
  compileTestJava - Compiles Java source 'test:java'.
  processTestResources - Processes JVM resources 'test:resources'.

...

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.[classes]

...

Verification tasks
------------------
check - Runs all checks.
test - Runs the unit tests.

Rules
-----
Pattern: clean<TaskName>: Cleans the output files of a task.
Pattern: build<ConfigurationName>: Assembles the artifacts of a configuration.
Pattern: upload<ConfigurationName>: Assembles and uploads the artifacts belonging to a configuration.

To see all tasks and more detail, run with --all.

BUILD SUCCESSFUL

The preceding output displays different build tasks, test tasks, documentation tasks, and other available tasks in the Java plugin. The output also shows the task dependencies between different tasks. For example, task classes internally depend on the compileJava and processResources tasks, which compile and process the source code and resources from src/main/java and src/main/resources, respectively. Similarly, the compileTestJava task and processTestResources task compile and process resources from src/test/java and src/test/resources, respectively. The output of all these tasks is compiled classes and resources, which will be created under the build directory by convention and will be added to the classspath during the execution of the program. Now, let us explore, with an example, what these tasks mean and which conventions are available by default.

To compile classes only under src/main, we should use the task classes. The compiled classes will be created under build/classes/ directory.

$ gradle classes
:compileJava
:processResources UP-TO-DATE
:classes

BUILD SUCCESSFUL

The testClasses task compiles and processes test classes and resources, and additionally, executes the classes task. In the following output, you can see that the compileJava, processResources, and classes tasks were executed again but the tasks were marked as UP-TO-DATE. This is because there was no change in the input and output of those tasks, as we have already executed the classes task in the last command. After successful execution, you will find a test directory created under the build/classes folder:

$ gradle testClasses
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses

BUILD SUCCESSFUL

The other important task is the test task. This task helps to execute unit test code written under the src/test directory. After successful execution, you will find the test results created under the build/test-results directory:

$ gradle test
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test

BUILD SUCCESSFUL

You have the assemble task or the jar task to package classes and resources into a jar file. The jar task will only create jar files, whereas, the assemble task helps you to produce other artifacts, including jar. For example, when you apply the war plugin, the jar task is disabled and is replaced with the war task. By default, the JAR file is named <project-name>.jar and is created under build/libs. If you have not set the <project-name> in the build file, you will get the jar name <project-folder-name>.jar. This is not good practice if the jar file does not contain any version. You can add the version to the jar file by adding the version property to your project in the build file, which will generate <name>-<version>.jar. In our example, the project name is Ch04-Java1 and the version property is set to 1.0 in the build file. Therefore, the jar file will be named Ch04-Java1-1.0.jar. Execute the following command and you will find the jar file under build/libs:

$ gradle assemble
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar
:assemble

BUILD SUCCESSFUL

Tip

No test classes will be packaged in the JAR file.

Another task is the build task, which executes the check and assemble tasks together. The clean task deletes all the artifacts created by another task. It actually deletes the complete build/ folder. This means, the clean task deletes the output generated by all the tasks, that is, check and assemble. To delete a task-specific output, we can apply the clean<TaskName> rule. For example, to delete only the jar file created by the build task, we can execute the gradle cleanJar command.

All the tasks in the Java plugin execute based on conventions such as source directory location, build folder name, test result folder, and so on. To understand this in a better way, the following example shows some of the conventions supported by Gradle:

task displayJavaPluginConvention << {

  println "Lib Directory: $libsDir"
  println "Lib Directory Name: $libsDirName"
  println "Reports Directory: $reportsDir"
  println "Test Result Directory: $testResultsDir"
  
  println "Source Code in two sourcesets: $sourceSets"
  println "Production Code: ${sourceSets.main.java.srcDirs}"
  println "Test Code: ${sourceSets.test.java.srcDirs}"
println "Production code output: ${sourceSets.main.output.classesDir} & ${sourceSets.main.output.resourcesDir}"
println "Test code output: ${sourceSets.test.output.classesDir} & ${sourceSets.test.output.resourcesDir}"
}

The output displays various conventions supported by the Java plugin. You can find the complete list in the official Gradle documentation at https://docs.gradle.org/current/userguide/java_plugin.html.

$ gradle displayJavaPluginConvention
:displayJavaPluginConvention
Lib Directory: <path>/build/libs
Lib Directory Name: libs
Reports Directory: <path>/build/reports
Test Result Directory: <path>/build/test-results
Source Code in two sourcesets: [source set 'main', source set 'test']
Production Code: [<path>/src/main/java]
Test Code: [<path>/src/test/java]
Production code output: <path>/build/classes/main & <path>/build/resources/main
Test code output: <path>/build/classes/test & <path>/build/resources/test

BUILD SUCCESSFUL

Sometimes, these default configurations might not suffice. We might need to configure some default properties to support our requirements. In the next section, we will explore how to configure some of the default configurations.

Configuration

In the previous example, we learned about the default properties or conventions available in the Java plugin. Now, we will configure some of these properties. This is important when we want to change the build directory name, the libs folder name, or the source file location of the project.

The source- related configuration changes can be set in the sourceSets closure. The upcoming code snippet (project name Ch04-Java2) shows that the source code location has been modified from src/main/java to src/productioncode for the source code location and src/test/java to src/testcode for the test code location, respectively. As a result, compiled classes will now be stored in classes/productioncode and classes/testcode locations for the source and test code, respectively. This will not replace the source directory from main to productioncode, but Gradle will now look for source code in both main and productioncode directories and for test code in both test and testcode directories. If you want Gradle to look for the source code only in the productioncode directory, you can set the java.srcDirs property.

These Java plugin conventions are written in the JavaPluginConvention and BasePluginConvention classes. One such property, testResultsDirName, can also be set in the build file:

buildDir = 'buildfolder'
libsDirName = 'libfolder'

sourceSets {
  main {
    java {
      srcDir 'src/productioncode/java'
    }
    resources {
      srcDir 'src/productioncode/resources'
    }
  }
  test{
  
    java {
      srcDir 'src/testcode/java'
    }
    resources {
      srcDir 'src/testcode/resources'
    }
  }
}

testResultsDirName = "$buildDir/new-test-result"
sourceSets.main.output.classesDir "${buildDir}/classes/productioncode/java"
sourceSets.main.output.resourcesDir "${buildDir}/classes/productioncode/resources"
sourceSets.test.output.classesDir "${buildDir}/classes/testcode/java"
sourceSets.test.output.resourcesDir "${buildDir}/classes/testcode/resources"

These changes will make sure that buildfolder, libfolder, and test-result folders have been replaced with buildfolder, libfolder, and new-test-result folders.

Figure 4.1 shows the directory structure of the src folder and new the buildfolder:

Configuration

Figure 4.1

All these new changes can be verified by executing the previously created displayJavaPluginConvention task. After executing the task, you will find the output updated with new configurations:

$ gradle displayJavaPluginConvention
:displayJavaPluginConvention
Lib Directory: <path>/buildfolder/libfolder
Lib Directory Name: libfolder
Reports Directory: <path>/buildfolder/reports
Test Result Directory: %path%/buildfolder/new-test-result
Source Code in two sourcesets: [source set 'main', source set 'test']
Production Code: [<path>/src/main/java, <path>/src/productioncode/java]
Test Code: [<path>/src/test/java, <path>/src/testcode/java]
Production code output: <path>/buildfolder/classes/productioncode/java & <path>/buildfolder/classes/productioncode/resources
Test code output: <path>/buildfolder/classes/testcode/java & <path>/buildfolder/classes/testcode/resources

BUILD SUCCESSFUL
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.63.95