Java Build (Maven & Gradle)
Build conventions, dependency management, multi-module projects, and CI patterns.
# CLAUDE.md — Java Build (Maven & Gradle)
## Pick one
- **Maven** for stability, predictability, and convention. Best for teams that don't want to debug their build tool.
- **Gradle** for performance and configurability. Best for monorepos and complex build logic.
- Don't mix. One per repo.
- Always commit the wrapper (`mvnw` or `gradlew`) — every machine builds the same way.
## Maven defaults
- `pom.xml`:
- `<maven.compiler.release>21</maven.compiler.release>`
- `<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>`
- Pin plugin versions explicitly. Don't rely on plugin version inheritance from the super-POM.
- Use **BOM imports** (`<dependencyManagement>`) for consistent versions across deps (Spring Boot BOM, JUnit BOM).
- Multi-module: parent POM declares `<modules>`, each module is its own pom inheriting from parent.
## Gradle defaults
- **Kotlin DSL** (`build.gradle.kts`) over Groovy. Better IDE support and type safety.
- Toolchains: `java { toolchain { languageVersion = JavaLanguageVersion.of(21) } }`. Gradle downloads the JDK automatically.
- `versionCatalog` (`gradle/libs.versions.toml`) for dep versions. One source of truth across modules.
- Build cache + configuration cache: `org.gradle.caching=true`, `org.gradle.configuration-cache=true`. Order-of-magnitude faster builds.
## Dependencies
- Pin every direct dependency. Use `mvn dependency:tree` / `gradle dependencies` to audit transitives.
- `provided` / `compileOnly` for deps the runtime supplies (servlet API in a WAR, BOM imports).
- `test` / `testImplementation` for test-only deps. They don't pollute the runtime classpath.
- Don't use SNAPSHOT versions in CI. Pin to a release.
## Multi-module structure
```
parent-pom.xml
app/ ← deployable
api/ ← interfaces
domain/ ← pure model
infrastructure/ ← external system adapters
```
- Domain and api have minimal deps. Infrastructure pulls in Postgres, HTTP clients, etc.
- App wires everything together. Should be the smallest module.
## CI
- One job per stage: compile, test, integration test, package.
- Use Maven's `-T` (parallel) or Gradle's parallelism for multi-module speedup.
- Cache `~/.m2` and `~/.gradle` between runs. Saves minutes per build.
- Fail on any new SpotBugs / SonarLint warnings — `--failOnWarning` style flags.
## Don't
- Don't commit the local Maven settings or Gradle init scripts to the repo.
- Don't put credentials in `pom.xml` or `build.gradle.kts`. Use `~/.m2/settings.xml` or env vars.
- Don't run plugins from `mvn clean install` you don't recognize. Audit `pom.xml` periodically.
- Don't use `version-range` syntax (`[1.0,2.0)`) in dependencies — it makes builds non-deterministic.
Other Java templates
Modern Java Rules
Java 21+ defaults: records, sealed types, pattern matching, virtual threads, var.
Java Testing with JUnit 5
JUnit 5 + AssertJ + Mockito + Testcontainers — opinionated test conventions.
Java Virtual Threads & Concurrency
Project Loom virtual threads, structured concurrency, and modern concurrent patterns.
Java Streams & Collections
Streams API, immutable collections, Collectors, and idiomatic data manipulation.
Spring Framework Core Rules
Dependency injection, bean lifecycle, configuration classes, and profiles.