Java Academy

Master Java Development

Menu

Core Java

Servlets

JDBC

Microservices

Build Tools

APIs

Build Tools · Lesson 5

Gradle Basics

What is Gradle?

Gradle is a modern build tool combining the best of Maven and Ant. Like Maven, it manages dependencies and has a standard project structure. Unlike Maven's declarative XML, Gradle uses Groovy or Kotlin scripts for build logic, offering more flexibility and power. Gradle incremental builds are faster than Maven's — it tracks what changed and recompiles only affected code. Gradle is popular in Android development and increasingly used for backend Java projects.

Gradle Project Structure and build.gradle

A Gradle project uses similar directory structure to Maven (src/main/java, src/test/java) but is configured in build.gradle (Groovy) or build.gradle.kts (Kotlin). Gradle's syntax is more concise than Maven's XML.

// build.gradle: Gradle build script (Groovy)

// Apply plugins
plugins {
    id 'java'
    id 'application'
    id 'org.springframework.boot' version '2.7.0'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
}

// Project metadata
group = 'com.example'
version = '1.0.0'
description = 'My Spring Boot Application'

// Java version
java {
    sourceCompatibility = '11'
    targetCompatibility = '11'
}

// Main class for application plugin
application {
    mainClass = 'com.example.App'
}

// Repositories for downloading dependencies
repositories {
    mavenCentral()  // Default Maven Central repository
}

// Dependencies
dependencies {
    // Spring Boot starter for web
    implementation 'org.springframework.boot:spring-boot-starter-web:2.7.0'
    
    // MySQL database driver
    runtimeOnly 'mysql:mysql-connector-java:8.0.33'
    
    // JUnit for testing
    testImplementation 'junit:junit:4.13.2'
    testImplementation 'org.springframework.boot:spring-boot-starter-test:2.7.0'
}

// Tasks
task hello {
    doLast {
        println 'Hello, Gradle!'
    }
}

// Custom task
task printVersion {
    doLast {
        println "Project version: ${version}"
    }
}

Gradle Build Lifecycle and Tasks

Gradle organizes work into tasks. Run tasks with gradle taskName. Common tasks: build, test, run, clean, jar, assemble. Tasks can depend on other tasks, forming a directed graph.

# Compile and run tests
gradle build

# Run tests only
gradle test

# Run the application
gradle run

# Clean build artifacts
gradle clean

# List all available tasks
gradle tasks

# Run specific task with dependencies
gradle jar

# Run task with dependencies and parameters
gradle run --args="arg1 arg2"

# Run in offline mode (no internet)
gradle build --offline

# Run with verbose output
gradle build --info

Gradle Dependency Configurations

Gradle configurations define how dependencies are used. Similar to Maven scopes but more flexible:

  • implementation: included in compilation and runtime (like Maven compile)
  • testImplementation: only for tests (like Maven test scope)
  • runtimeOnly: not needed for compilation, only runtime (like Maven runtime)
  • compileOnly: needed for compilation, not runtime
// build.gradle: Dependency configurations

dependencies {
    // Compile and runtime (main code and tests)
    implementation 'org.springframework.boot:spring-boot-starter-web:2.7.0'
    
    // Only for testing
    testImplementation 'junit:junit:4.13.2'
    testImplementation 'org.mockito:mockito-core:4.6.1'
    
    // Only at runtime (not compiled with)
    runtimeOnly 'mysql:mysql-connector-java:8.0.33'
    
    // Only for compilation (e.g., annotations, not runtime)
    compileOnly 'org.projectlombok:lombok:1.18.24'
    annotationProcessor 'org.projectlombok:lombok:1.18.24'
    
    // Exclude transitive dependency
    implementation ('org.springframework.boot:spring-boot-starter-web:2.7.0') {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
    }
}

Gradle Multi-Project Builds

For large projects with multiple modules, Gradle's multi-project builds are powerful. A root settings.gradle defines modules; each module has its own build.gradle. Modules can share common configuration through a buildSrc/ directory.

// Project structure
my-project/
├── settings.gradle           # Define modules
├── build.gradle              # Root configuration
├── buildSrc/
│   └── build.gradle          # Shared build logic
├── user-service/
│   └── build.gradle
├── product-service/
│   └── build.gradle
└── payment-service/
    └── build.gradle
// settings.gradle: Define modules
rootProject.name = 'my-project'
include 'user-service'
include 'product-service'
include 'payment-service'
// build.gradle (root): Shared configuration
subprojects {
    apply plugin: 'java'
    
    group = 'com.example'
    version = '1.0.0'
    
    java {
        sourceCompatibility = '11'
        targetCompatibility = '11'
    }
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        // Shared test dependency
        testImplementation 'junit:junit:4.13.2'
    }
}
// user-service/build.gradle: Module-specific configuration
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'mysql:mysql-connector-java'
}
# Build all modules
gradle build

# Build specific module
gradle :user-service:build

# Run tests in specific module
gradle :user-service:test

Gradle Tasks and Custom Plugins

Create custom tasks for automation. Tasks can depend on other tasks, run in sequence or parallel.

// build.gradle: Custom tasks

// Simple task
task sayHello {
    doLast {
        println 'Hello from Gradle!'
    }
}

// Task that depends on other task
task buildAndTest {
    dependsOn 'build', 'test'
}

// Task with input/output
task processData {
    inputs.files 'data/input.txt'
    outputs.file 'data/output.txt'
    
    doLast {
        println 'Processing data...'
        // Read input, process, write output
    }
}

// Custom plugin (in buildSrc/)
class VersionPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.task('printVersion') {
            doLast {
                println "Version: ${project.version}"
            }
        }
    }
}

apply plugin: VersionPlugin
FeatureMavenGradle
ConfigurationXML (pom.xml)Groovy/Kotlin script (build.gradle)
FlexibilityLess (conventions-driven)More (script-based)
PerformanceStandardFaster (incremental builds)
Learning CurveEasierSteeper
Popular UseEnterprisesAndroid, modern Java projects
Build ScriptsDeclarativeImperative

Common Mistake: Gradle scripts can become complex quickly. Keep build logic simple and delegate complex tasks to plugins. Also, Gradle can be slower on first run (building cache); subsequent builds are much faster. Don't be alarmed by initial slowness — it's the trade-off for flexibility.

Best Practices for Gradle

  • Use Gradle Wrapper (gradlew script) to ensure consistent Gradle version across team
  • Keep build.gradle simple: extract complex logic to buildSrc/ or plugins
  • Use version catalogs for managing dependency versions (Gradle 7.1+)
  • Apply plugins explicitly: don't rely on implicit configuration
  • Test build scripts: complex Gradle scripts deserve unit tests
  • Use dependency constraints for conflict resolution
  • Enable build cache for faster CI/CD pipelines
  • Document custom tasks so team understands what they do

Real-World Example: Microservices with Gradle

A microservices project uses Gradle with subprojects: api-gateway, user-service, product-service, payment-service. The root build.gradle applies common configuration (Java 11, Spring Boot, test framework) to all modules. Each service's build.gradle adds specific dependencies. Running gradle build compiles and tests all services in parallel. gradle :user-service:bootRun starts just the user service with embedded Tomcat. Gradle wrapper (gradlew) ensures all developers use Gradle 7.5, preventing "works on my machine" issues. Custom tasks automate deployment: gradle deploy builds all services and pushes Docker images to registry.

Quiz Check

Quick Knowledge Test

Loading quiz questions...