Gradle is a powerful build automation tool that uses a Groovy or Kotlin DSL. This guide covers comprehensive Gradle build scripts for Java projects.
1. Basic Java Project Setup
Basic build.gradle
plugins {
id 'java'
id 'application'
}
group = 'com.example'
version = '1.0.0'
description = 'A simple Java application'
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
repositories {
mavenCentral()
google()
maven { url 'https://jitpack.io' }
}
dependencies {
// Production dependencies
implementation 'com.google.guava:guava:31.1-jre'
implementation 'org.apache.commons:commons-lang3:3.12.0'
// Test dependencies
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
testImplementation 'org.mockito:mockito-core:5.3.1'
testImplementation 'org.assertj:assertj-core:3.24.2'
// Runtime dependencies
runtimeOnly 'ch.qos.logback:logback-classic:1.4.6'
}
application {
mainClass = 'com.example.Main'
}
test {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed"
exceptionFormat "full"
}
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
options.compilerArgs += ['-Xlint:unchecked', '-Xlint:deprecation']
}
jar {
manifest {
attributes(
'Main-Class': 'com.example.Main',
'Implementation-Title': project.name,
'Implementation-Version': project.version,
'Built-By': System.getProperty('user.name'),
'Built-Date': new Date(),
'Built-JDK': System.getProperty('java.version')
)
}
}
settings.gradle for Basic Project
rootProject.name = 'my-java-app' // Include subprojects if any // include 'subproject1', 'subproject2'
2. Multi-Project Build
Root settings.gradle
rootProject.name = 'enterprise-app'
include 'core'
include 'web-api'
include 'batch-processor'
include 'shared-lib'
include 'integration-tests'
// Custom project paths
project(':core').projectDir = file('modules/core')
project(':web-api').projectDir = file('modules/web-api')
project(':batch-processor').projectDir = file('modules/batch')
project(':shared-lib').projectDir = file('libs/shared')
project(':integration-tests').projectDir = file('testing/integration')
Root build.gradle
plugins {
id 'java'
id 'idea'
id 'eclipse'
}
allprojects {
group = 'com.enterprise'
version = '2.0.0'
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}
}
subprojects {
apply plugin: 'java'
apply plugin: 'jacoco'
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
dependencies {
implementation 'org.slf4j:slf4j-api:2.0.7'
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
testImplementation 'org.mockito:mockito-core:5.3.1'
}
test {
useJUnitPlatform()
maxHeapSize = '1G'
testLogging {
events "passed", "skipped", "failed"
}
}
jacoco {
toolVersion = "0.8.8"
}
jacocoTestReport {
dependsOn test
reports {
xml.required = true
html.required = true
csv.required = false
}
}
}
// Project-specific configurations
project(':core') {
dependencies {
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
}
}
project(':web-api') {
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
dependencies {
implementation project(':core')
implementation project(':shared-lib')
implementation 'org.springframework.boot:spring-boot-starter-web:3.0.6'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.0.6'
}
}
project(':batch-processor') {
dependencies {
implementation project(':core')
implementation 'org.springframework.boot:spring-boot-starter-batch:3.0.6'
}
}
project(':shared-lib') {
// Shared library configuration
}
project(':integration-tests') {
dependencies {
implementation project(':web-api')
implementation project(':batch-processor')
testImplementation 'io.rest-assured:rest-assured:5.3.0'
}
}
3. Spring Boot Application
Spring Boot build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.0'
id 'io.spring.dependency-management' version '1.1.0'
id 'com.github.ben-manes.versions' version '0.46.0'
}
group = 'com.example'
version = '2.1.0'
sourceCompatibility = '17'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
developmentOnly
runtimeClasspath {
extendsFrom developmentOnly
}
}
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}
ext {
set('springCloudVersion', "2022.0.3")
set('testcontainersVersion', "1.18.0")
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
mavenBom "org.testcontainers:testcontainers-bom:${testcontainersVersion}"
}
}
dependencies {
// Spring Boot Starters
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-cache'
// Database
implementation 'org.postgresql:postgresql:42.6.0'
implementation 'com.h2database:h2'
implementation 'org.flywaydb:flyway-core'
// Cache
implementation 'com.github.ben-manes.caffeine:caffeine:3.1.6'
// API Documentation
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
// Security
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
// Utilities
implementation 'com.google.guava:guava:31.1-jre'
implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation 'org.modelmapper:modelmapper:3.1.1'
// Development
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'
// Testing
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation 'org.testcontainers:postgresql'
testImplementation 'com.tngtech.archunit:archunit-junit5:1.0.1'
}
bootRun {
systemProperties = System.properties
jvmArgs = [
'-Xmx512m',
'-Dspring.profiles.active=dev',
'-Djava.security.egd=file:/dev/./urandom'
]
}
bootJar {
archiveFileName = "${project.name}-${project.version}.jar"
launchScript()
manifest {
attributes(
'Implementation-Title': project.name,
'Implementation-Version': project.version,
'Built-By': System.getProperty('user.name'),
'Build-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
'Created-By': "Gradle ${gradle.gradleVersion}",
'Build-Jdk': System.getProperty('java.version')
)
}
}
test {
useJUnitPlatform()
systemProperty 'spring.profiles.active', 'test'
testLogging {
events "passed", "skipped", "failed"
exceptionFormat "full"
showStandardStreams = true
}
reports {
html.required = true
junitXml.required = true
}
maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
}
tasks.named('dependencyUpdates').configure {
checkForGradleUpdate = true
outputDir = "build/dependencyUpdates"
reportfileName = "report"
rejectVersionIf {
isNonStable(candidate.version) && !isNonStable(currentVersion)
}
}
static boolean isNonStable(String version) {
return ['alpha', 'beta', 'rc', 'cr', 'm', 'preview', 'b', 'ea'].any {
version.toLowerCase().contains(it)
}
}
// Custom task for code quality
task codeQualityCheck {
group = 'verification'
description = 'Runs all code quality checks'
dependsOn test, jacocoTestReport
}
// Generate build info
task generateBuildInfo {
doLast {
def buildInfoFile = new File("$buildDir/resources/main/build-info.properties")
buildInfoFile.parentFile.mkdirs()
buildInfoFile.text = """
build.version=${project.version}
build.timestamp=${new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")}
build.java.version=${System.getProperty('java.version')}
build.os.name=${System.getProperty('os.name')}
""".stripIndent().trim()
}
}
processResources.dependsOn generateBuildInfo
4. Advanced Configuration with Custom Tasks
Advanced build.gradle with Custom Tasks
plugins {
id 'java'
id 'jacoco'
id 'checkstyle'
id 'pmd'
id 'com.github.spotbugs' version '5.0.14'
id 'org.sonarqube' version '4.0.0.2929'
id 'com.bmuschko.docker-java-application' version '9.3.1'
}
group = 'com.enterprise'
version = '3.0.0'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
repositories {
mavenCentral()
maven { url 'https://plugins.gradle.org/m2/' }
}
configurations {
codeQuality
asciidoclet
}
dependencies {
implementation 'io.vavr:vavr:0.10.4'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2'
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
testImplementation 'org.assertj:assertj-core:3.24.2'
testImplementation 'org.mockito:mockito-core:5.3.1'
testImplementation 'org.testcontainers:testcontainers:1.18.0'
codeQuality 'com.puppycrawl.tools:checkstyle:10.9.3'
codeQuality 'net.sourceforge.pmd:pmd-java:6.55.0'
codeQuality 'com.github.spotbugs:spotbugs:4.7.3'
asciidoclet 'org.asciidoctor:asciidoclet:2.0.0'
}
// Checkstyle Configuration
checkstyle {
toolVersion = '10.9.3'
config = resources.text.fromUri('https://checkstyle.org/sun_checks.xml')
maxErrors = 0
maxWarnings = 10
}
tasks.withType(Checkstyle) {
reports {
xml.required = false
html.required = true
}
exclude '**/generated/**'
}
// PMD Configuration
pmd {
toolVersion = '6.55.0'
ruleSetFiles = files("$projectDir/config/pmd/ruleset.xml")
ruleSets = []
ignoreFailures = false
}
tasks.withType(Pmd) {
reports {
xml.required = false
html.required = true
}
}
// SpotBugs Configuration
spotbugs {
toolVersion = '4.7.3'
effort = 'max'
reportLevel = 'low'
excludeFilter = file("$projectDir/config/spotbugs/exclude.xml")
}
tasks.withType(com.github.spotbugs.snom.SpotBugsTask) {
reports {
html.required = true
xml.required = false
}
}
// JaCoCo Configuration
jacoco {
toolVersion = "0.8.8"
}
jacocoTestReport {
dependsOn test
reports {
xml.required = true
html.required = true
csv.required = false
}
executionData fileTree(project.rootDir.absolutePath).include("**/build/jacoco/*.exec")
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
'**/config/**',
'**/entity/**',
'**/dto/**',
'**/*Application*'
])
}))
}
}
jacocoTestCoverageVerification {
violationRules {
rule {
limit {
minimum = 0.8
}
}
rule {
element = 'CLASS'
excludes = [
'*.config.*',
'*.entity.*',
'*.dto.*',
'*Application*'
]
limit {
counter = 'LINE'
value = 'COVEREDRATIO'
minimum = 0.7
}
}
}
}
// SonarQube Configuration
sonarqube {
properties {
property "sonar.projectKey", "enterprise-java-app"
property "sonar.projectName", "Enterprise Java Application"
property "sonar.coverage.jacoco.xmlReportPaths", "${buildDir}/reports/jacoco/test/jacocoTestReport.xml"
property "sonar.java.checkstyle.reportPaths", "${buildDir}/reports/checkstyle/main.xml"
property "sonar.pmd.reportPaths", "${buildDir}/reports/pmd/main.html"
property "sonar.spotbugs.reportPaths", "${buildDir}/reports/spotbugs/main.xml"
}
}
// Docker Configuration
docker {
javaApplication {
baseImage = 'eclipse-temurin:17-jre-alpine'
maintainer = 'Dev Team <[email protected]>'
ports = [8080, 8081]
images = ["${project.group}/${project.name}:${project.version}"]
jvmArgs = ['-Xmx512m', '-Dspring.profiles.active=prod']
}
}
// Custom Tasks
task codeQuality(group: 'verification') {
description = 'Runs all code quality tools'
dependsOn checkstyleMain, checkstyleTest, pmdMain, pmdTest, spotbugsMain, spotbugsTest
}
task securityScan(group: 'verification') {
description = 'Runs security scans'
dependsOn dependencyCheckAnalyze
}
task qualityGate(group: 'verification') {
description = 'Runs complete quality gate'
dependsOn test, jacocoTestReport, jacocoTestCoverageVerification, codeQuality, securityScan
}
// Build lifecycle customization
test.finalizedBy jacocoTestReport
check.dependsOn jacocoTestCoverageVerification
build.dependsOn qualityGate
// Performance optimization
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
options.incremental = true
options.fork = true
options.forkOptions.memoryMaximumSize = '1g'
}
tasks.withType(Test) {
maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
forkEvery = 100
maxHeapSize = '1G'
}
// Resource filtering
processResources {
filesMatching('**/application*.yml') {
filter org.apache.tools.ant.filters.ReplaceTokens, tokens: [
'app.version': project.version,
'app.name': project.name
]
}
}
// Generate Javadoc with custom options
javadoc {
options {
encoding = 'UTF-8'
charSet = 'UTF-8'
docEncoding = 'UTF-8'
addBooleanOption('Xdoclint:all,-missing', true)
addStringOption('Xmaxwarns', '1000')
}
options.addStringOption('taglet', 'org.asciidoctor.Asciidoclet')
options.addStringOption('tagletpath', configurations.asciidoclet.files.asPath)
exclude '**/internal/**'
}
// Custom task to generate dependency report
task dependencyReport(type: DependencyReportTask) {
outputFile = file("${buildDir}/reports/dependencies.txt")
}
// Task to update wrapper
task updateWrapper(type: Wrapper) {
gradleVersion = '8.2.1'
distributionType = Wrapper.DistributionType.ALL
}
5. Microservices Build Setup
Microservice build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.0'
id 'io.spring.dependency-management' version '1.1.0'
id 'com.google.cloud.tools.jib' version '3.3.1'
}
group = 'com.microservices'
version = '1.0.0-' + (System.getenv('BUILD_NUMBER') ?: 'SNAPSHOT')
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}
ext {
set('springCloudVersion', "2022.0.3")
set('testcontainersVersion', "1.18.0")
set('resilience4jVersion', "2.0.2")
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
mavenBom "org.testcontainers:testcontainers-bom:${testcontainersVersion}"
}
}
dependencies {
// Spring Boot
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
// Spring Cloud
implementation 'org.springframework.cloud:spring-cloud-starter-config'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j'
implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
implementation 'org.springframework.cloud:spring-cloud-sleuth-zipkin'
// Resilience4j
implementation "io.github.resilience4j:resilience4j-spring-boot2:${resilience4jVersion}"
implementation "io.github.resilience4j:resilience4j-all:${resilience4jVersion}"
// Database
implementation 'org.postgresql:postgresql:42.6.0'
implementation 'org.flywaydb:flyway-core'
// API
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
implementation 'io.micrometer:micrometer-registry-prometheus'
// Messaging
implementation 'org.springframework.kafka:spring-kafka'
// Caching
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
// Security
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
// Utilities
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
// Testing
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.kafka:spring-kafka-test'
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation 'org.testcontainers:postgresql'
testImplementation 'org.testcontainers:kafka'
}
// Jib Configuration for Docker image building
jib {
from {
image = 'eclipse-temurin:17-jre-alpine'
platforms {
platform {
architecture = 'amd64'
os = 'linux'
}
platform {
architecture = 'arm64'
os = 'linux'
}
}
}
to {
image = "registry.example.com/microservices/${project.name}"
tags = ['latest', project.version]
auth {
username = System.getenv('DOCKER_USERNAME')
password = System.getenv('DOCKER_PASSWORD')
}
}
container {
jvmFlags = [
'-Xms256m',
'-Xmx512m',
'-Dspring.profiles.active=prod',
'-Djava.security.egd=file:/dev/./urandom'
]
ports = ['8080']
environment = [
'SPRING_PROFILES_ACTIVE': 'prod',
'JAVA_OPTS': '-Xmx512m'
]
labels = [
'maintainer': 'Microservices Team',
'version': project.version,
'description': project.description
]
creationTime = 'USE_CURRENT_TIMESTAMP'
}
}
// Spring Boot specific configurations
bootRun {
systemProperties = System.properties
jvmArgs = [
'-Dspring.profiles.active=dev',
'-Dspring.cloud.config.uri=http://localhost:8888'
]
}
bootBuildImage {
imageName = "microservices/${project.name}:${project.version}"
environment = [
"BPE_DELIM_JAVA_TOOL_OPTIONS" : " ",
"BPE_APPEND_JAVA_TOOL_OPTIONS" : "-Xmx512m -Dspring.profiles.active=prod"
]
}
// Test configuration for microservices
test {
useJUnitPlatform()
systemProperty 'spring.profiles.active', 'test'
filter {
includeTestsMatching '*Test'
excludeTestsMatching '*IT'
}
}
task integrationTest(type: Test) {
useJUnitPlatform()
systemProperty 'spring.profiles.active', 'integration-test'
filter {
includeTestsMatching '*IT'
}
shouldRunAfter test
}
task smokeTest(type: Test) {
useJUnitPlatform()
systemProperty 'spring.profiles.active', 'smoke-test'
filter {
includeTestsMatching '*ST'
}
shouldRunAfter integrationTest
}
// Task dependencies
check.dependsOn integrationTest
build.dependsOn smokeTest
// Generate OpenAPI spec
task generateOpenApiSpec {
doLast {
javaexec {
main = 'org.springframework.boot.loader.JarLauncher'
classpath = bootJar.outputs.files
systemProperties = [
'spring.profiles.active': 'docs',
'spring.main.web-application-type': 'none'
]
}
}
}
// Custom task for database migration
task dbMigrate {
doLast {
javaexec {
main = 'org.flywaydb.commandline.Main'
classpath = configurations.runtimeClasspath
args = [
'-url=jdbc:postgresql://localhost:5432/mydb',
'-user=admin',
'-password=secret',
'migrate'
]
}
}
}
6. gradle.properties Configuration
Common gradle.properties
# Project Properties org.gradle.project.name=my-java-app org.gradle.project.description=A modern Java application org.gradle.project.url=https://github.com/example/my-java-app org.gradle.project.inceptionYear=2023 # Build Performance org.gradle.parallel=true org.gradle.caching=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 # Daemon Configuration org.gradle.daemon=true org.gradle.daemon.idletimeout=10800000 # Logging org.gradle.console=plain org.gradle.logging.level=info # Dependency Resolution org.gradle.resolution.parallel=true org.gradle.resolution.runtime.mode=auto # Testing org.gradle.test.worker.max=4 # Publishing org.gradle.publish.overwrite=false # Plugin Versions (for settings.gradle) springBootVersion=3.1.0 springDependencyManagementVersion=1.1.0 jacocoVersion=0.8.8 sonarqubeVersion=4.0.0.2929 jibVersion=3.3.1
Key Gradle Concepts for Java
- Plugins: Extend build functionality (java, spring-boot, etc.)
- Dependencies: implementation, testImplementation, runtimeOnly
- Tasks: Custom build operations
- Configurations: Dependency scopes and custom configurations
- Properties: Project properties and system properties
- Multi-project: Complex project structures with dependencies
- Performance: Caching, parallel execution, incremental builds
- Quality: Integration with code quality tools
- Containerization: Docker image building with Jib
- CI/CD: Integration with Jenkins, GitHub Actions, etc.
This comprehensive guide covers Gradle build scripts for various Java project types, from simple applications to complex microservices architectures.