banner
jzman

jzman

Coding、思考、自觉。
github

Java Gradle Plugin in the Gradle Series

In the previous articles, we learned the basics of Gradle build tasks. It is recommended to read the earlier articles:

In the previous article, we learned about Gradle plugins and how to customize a Gradle plugin. This article mainly focuses on Java Gradle plugin-related knowledge, as the content related to the Java Gradle plugin is also the foundation for the Android Gradle plugin. Using Gradle to build projects is essentially about helping developers perform repetitive tasks, such as configuring third-party dependencies, compiling source files, unit testing, packaging, and publishing. Using the corresponding Gradle plugins can facilitate project building and improve development efficiency to a certain extent. The main content we will learn today includes:

  1. Using the Java Gradle Plugin
  2. Project Structure Conventions for Java Plugin
  3. Configuring Third-Party Dependencies
  4. How to Build a Java Project
  5. Concept of SourceSet
  6. Tasks that can be added by the Java Plugin
  7. Properties that can be added by the Java Plugin
  8. Multi-Project Builds
  9. Publishing Artifacts

Using the Java Gradle Plugin#

To use a Gradle plugin, the Project's apply() method is used:

// java is the plugin id for the Java Gradle plugin
apply plugin: 'java'

After using the Java plugin, default settings and conventions will be added to the current project, such as the location of source code, unit test code, resource files, etc. Generally, the default settings can be used.

Project Structure Conventions for Java Plugin#

The Java plugin sets some default settings and conventions. Let's take a look at the default project directory for a Java project, which is generally structured as follows:

JavaGradle
└─src
    ├─main
    │  ├─java
    │  └─resources
    └─test
        ├─java
        └─resources

In the above directory structure, src/main/java is the default directory for source code, src/main/resources is the directory for resource files and configuration files, and the directories under src/test are, of course, for storing files related to unit tests. main and test are the two built-in source sets in the Java Gradle plugin. Besides these, you can define other source sets as follows:

apply plugin: 'java'

sourceSets {
    // Specify a new source set
    vip {
        
    }
}

Then create the corresponding java and resources directories under src, with the contents of the files in these directories being similar to the defaults. The default directory structure is as follows:

// Source code directory
src/vip/java
// Resource files directory
src/vip/resource

The above directory structure is the default implementation of the Java Gradle plugin. You can also modify the specific directory locations, configured as follows:

sourceSets {
    // Modify the default directories; the following are still the same as the default locations, modify as needed
    main {
        java {
            srcDir 'src/java'
        }
        
        resources {
            srcDir 'src/resources'
        }
        
    }
}

Configuring Third-Party Dependencies#

During development, third-party jar packages are often used, and at this point, dependency configuration for the jar packages is necessary. The types of repositories and their locations need to be specified. When configuring dependencies, Gradle will look for the relevant dependencies in the specified repositories. The configuration for repositories and specific dependencies is as follows:

// Configure repository locations
repositories {
    // Repository types such as jcenter, ivy, maven central, maven local, maven private server, etc.
    mavenCentral()
    mavenLocal()
    maven {
        uri "http" //xxxx
    }
    jcenter()
    google()
    //...
}

// Configure specific dependencies
dependencies {
    // Three elements of a dependency: group, name, version
    // Corresponding to Maven's GAV (groupId, artifactId, version)
    
    // Full syntax
    compile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.0.1'
    // Short syntax
    compile 'com.squareup.okhttp3:okhttp:3.0.1'
}

In the above code, compile is a compile-time dependency. Gradle also provides other dependency types, as follows:

compile: Compile-time dependency
runtime: Runtime dependency
testCompile: Compile-time dependency for testing
testRuntime: Dependency only during test case execution
archives: Dependency for publishing artifacts, such as jar packages
default: Default dependency configuration

After Gradle 3.0, implementation and api will replace compile. We won't elaborate on these two dependency types here, as learning the new API is not the focus of this article. The Java Gradle plugin also supports specifying different dependencies for different source sets, as follows:

// Configure different dependencies for different source sets
dependencies {
    // Configuration format: sourceSetCompile, sourceSetRuntime
    mainCompile 'com.squareup.okhttp3:okhttp:3.0.1'
    vipCompile 'com.squareup.okhttp3:okhttp:2.0.1'
}

The above describes the dependency on an external library. Additionally, during development, you may encounter module dependencies and file dependencies. In fact, module dependencies refer to dependencies on a subproject, while file dependencies generally refer to jar package dependencies.

In the article on the basics of build scripts in the Gradle series, it has been established that to build a subproject, the include keyword must be used in the settings.gradle file to include the subproject. The same applies here; now the projects to be depended upon must be included in the settings.gradle file, and then a specific subproject can be depended upon as follows:

// Depend on a subproject
dependencies {
    // Include ':childProject' in the settings.gradle file
    
    // Depend on the subproject
    compile project('childProject')
}

File dependencies mainly refer to jar package dependencies. Generally, jar packages are placed in the project's libs directory, and then the jar packages are referenced, as follows:

// Depend on a jar package
dependencies {
    // Configure a single jar
    compile file('libs/java1.jar')
    // Configure multiple jars
    compile files('libs/java1.jar', 'libs/java2.jar')
    // Batch configure jars; by configuring the path where the jars are located, all files with the jar suffix will be included in the project
    compile fileTree(dir: 'libs', include: '*.jar')
}

How to Build a Java Project#

All operations in Gradle are based on tasks, and the Java Gradle plugin also comes with a series of tasks to help us build projects. Executing the build task will start building the current project. You can use gradlew build to begin executing the build task. Gradle will compile source code files, process resource files, generate jar packages, compile test code, run unit tests, etc.

For example, in Android development, there is a clean task. Executing the clean operation will delete the build folder and other files generated during the project build. If there is a compilation error, you can try to clean and then build again. Additionally, there is a check task, which will be used during unit testing. The javadoc task can conveniently generate Java-formatted API documentation. Learning how to build a Java project is still for preparing to learn about building Android projects, so this concludes how to use Gradle to build a Java project.

Concept of SourceSet#

In this section, we will get to know SourceSet, which is the source set mentioned earlier. It is an abstract concept used by the Java Gradle plugin to describe and manage source code and its resources. It is a collection of Java source files and resource files, allowing you to configure the location of source files and set properties for the source set. Source sets can group and manage source code based on different business needs, such as the main and test source directories provided by the Java Gradle plugin by default, one for business code and the other for unit tests, which is very convenient.

The Java Gradle plugin provides a sourceSet property and a sourceSet{} closure under the Project to access and configure source sets. sourceSet is a SourceSetContainer, and the common properties of source sets are as follows:

// For example, main, test, etc. represent the names of source sets
name(String)
// Represents the directory for class files generated after compilation
output.classDir(File)
// Represents the directory for resource files generated after compilation
output.resourcesDir(File)
// Represents the classpath required for the source set after compilation
compileClasspath(FileCollection)
// Represents the Java source files for the source set
java(SourceDirectorySet)
// Represents the directory where the Java source files for the source set are located
java.srcDirs(Set)
// Represents the resource files for the source set
resources(SourceDirectorySet)
// Represents the directory where the resource files for the source set are located
resources.srcDirs(Set)

Below is how to set the output directory for the main source set:

// Set properties for a specific source set
sourceSets {
    main {
        // Source set name is read-only
        println name
        // Other property settings
        // From 4.0 onwards, this has been deprecated. The replacement is dir
        output.classesDir = file("a/b")
//        output.dir("a/b")
        output.resourcesDir = file("a/b")
        //....
    }
}

Tasks that can be added by the Java Plugin#

The project build is still carried out through a series of tasks provided by Gradle plugins. Below are commonly used tasks in Java projects:

Task NameTypeDescription
Default source set common tasks
compileJavaJavaCompileIndicates using javac to compile Java source files
processResourcesCopyIndicates copying resource files to the generated resource file directory
classesTaskIndicates assembling the generated class and resource file directory
compileTestJavaJavaCompileIndicates using javac to compile test Java source files
processTestResourcesCopyIndicates copying resource files to the generated resource file directory
testClassesTaskIndicates assembling the generated test classes and related resource files
jarJarIndicates assembling a jar file
javadocJavadocIndicates using javadoc to generate Java API documentation
uploadArchivesUploadIndicates uploading the build containing the Jar, configured using the archives{} closure
cleanDeleteIndicates cleaning the generated directory files from the build
cleanTaskNameDeleteIndicates deleting files generated by a specific task, such as cleanJar which deletes files generated by the jar task
Custom source set tasks(SourceSet is the specific source set name)
compileSourceSetJavaJavaCompileIndicates using javac to compile the source code of the specified source set
processSourceSetResourcesCopyIndicates copying the resource files of the specified source set to the resource directory in the generated files
sourcesSetClassesTaskIndicates assembling the classes and resource file directory for the given source set

Properties that can be added by the Java Plugin#

Common properties in the Java Gradle plugin are added to the Project, and these properties can be used directly, as follows:

Property NameTypeDescription
sourceSetsSourceSetContainerThe source sets of the Java project, which can be configured within the closure
sourceCompatibilityJavaVersionThe Java version used to compile Java source files
targetCompatibilityJavaVersionThe Java version for the generated classes
archivesBaseNameStringThe name of the jar or zip file to be packaged
manifestManifestUsed to access and configure the manifest file
libsDirFileThe directory for storing generated libraries
distsDirFileThe directory for storing generated release files

Multi-Project Builds#

Using Gradle for multi-project builds generally involves a main project depending on other submodule projects. Whether to build these subprojects is mainly configured in the settings.gradle file. To use these subprojects, project dependencies must be configured in the main project. The three types of dependencies mentioned earlier are library dependencies, project dependencies, and file dependencies. Here, project dependencies are used, and subprojects and allprojects are frequently used in multi-project configurations, as follows:

// Unified configuration for subprojects
subprojects {
    // Configure all subprojects to use the Java Gradle plugin
    apply plugin: 'java'
    // Configure all subprojects to use the Maven central repository
    repositories {
        mavenCentral()
    }
    // Other common configurations
    //...
}
// Unified configuration for all projects
allprojects {
    // Configure all projects to use the Java Gradle plugin
    apply plugin: 'java'
    // Configure all projects to use the Maven central repository
    repositories {
        mavenCentral()
    }
    // Other common configurations
    //...
}

Publishing Artifacts#

The products of Gradle builds are generally referred to as artifacts. A build can be a jar package, zip package, etc. So how do we publish artifacts? Below is how to publish a jar artifact to the local project folder or mavenLocal(), as follows:

/**
 * Publish artifacts to the project folder or mavenLocal()
 */
apply plugin: 'java'
// Task to generate jar, similar to custom wrapper
task publishJar(type: Jar)
// Artifact version
version '1.0.0'
// Artifact configuration through artifacts{} closure
artifacts {
    archives publishJar
}
// Artifact publishing upload
uploadArchives {
    repositories {
        flatDir {
            name 'libs'
            dirs "$projectDir/libs"
        }
        // Publish the build to mavenLocal()
        mavenLocal()
    }
}

Executing the uploadArchives task will generate the corresponding jar file in the appropriate location. The command is as follows:

// Execute uploadArchives
gradle uploadArchives

After successful execution, you will see the generated jar file in the project's libs directory, as shown in the following image:

image

After successful execution, you will also see the generated jar file in the user's .m2/repository directory, as shown in the following image:

image

Below is how to publish the jar to a built maven private server, with the code as follows:

/**
 * Publish artifacts to a maven private server
 */
apply plugin: 'java'
apply plugin: 'maven'
// Task to generate jar, similar to custom wrapper
task publishJar(type: Jar)
// Artifact version
version '1.0.0'
// Artifact configuration through artifacts{} closure
artifacts {
    archives publishJar
}
// Artifact publishing upload
uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: 'http://xxx') {
                // Repository username and password
                authentication(userName: 'username', password: 'pass')
            }
            snapshotRepository(url: 'http://xxx') {
                authentication(userName: 'username', password: 'pass')
            }
        }
    }
}

The upload process also involves executing the uploadArchives task. If you have a maven private server, you can give it a try. This concludes the study of the Java Gradle plugin, and the next article will officially begin the study of the Android Gradle plugin.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.