Maven vs Gradle — building
Every Java project needs a build tool — it manages dependencies, compiles, tests and packages. Two dominate the ecosystem: Maven (declarative, XML) and Gradle (flexible, a Kotlin/Groovy script). This lesson compares them and shows our conventions.
Maven — the declarative standard
Maven describes the project in pom.xml and works according to a fixed
lifecycle (validate → compile → test → package → install → deploy). Simple,
predictable.
<project>
<groupId>com.professnet.zeus</groupId>
<artifactId>inventory-service</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.release>21</maven.compiler.release>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
mvn clean verify # compilation + tests + checks
mvn package # build the artifact (jar)
Gradle — flexible and fast
Gradle uses a script (we prefer the Kotlin DSL — build.gradle.kts). It is
faster thanks to a build cache and incremental builds, but it demands more
discipline.
plugins {
java
id("org.springframework.boot") version "3.3.0"
}
java {
toolchain { languageVersion = JavaLanguageVersion.of(21) }
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
./gradlew build # compilation + tests
./gradlew bootJar # Spring Boot artifact
Comparison
| Feature | Maven | Gradle |
|---|---|---|
| Configuration | XML, declarative | Kotlin/Groovy, programmable |
| Learning curve | gentle | steep |
| Speed | slower | faster (cache, incremental) |
| Flexibility | limited | very high |
| Readability for newcomers | high | depends on discipline |
ProfessNet standard: for simple, typical services we choose Maven (predictability, a low barrier to entry). For large, multi-module projects and monorepos where build time matters — Gradle with the Kotlin DSL.
Wrapper — a reproducible build
We always commit the wrapper (mvnw / gradlew). It guarantees that everyone
builds with the same version of the tool, regardless of what they have on their
machine.
./mvnw clean verify # not 'mvn' — the wrapper from the repo
./gradlew build # not 'gradle'
ProfessNet standard: in CI and locally we use the wrapper, not a global installation. The tool version is pinned by
.mvn/wrapperorgradle/wrapper/gradle-wrapper.properties.
Dependencies — scopes and BOM
We pin the versions of related libraries via a BOM (e.g. Spring Boot dependencies) so we don't manage each version separately.
| Scope (Maven / Gradle) | Meaning |
|---|---|
compile / implementation | available at compile and runtime |
provided / compileOnly | compile only (e.g. Lombok) |
test / testImplementation | tests only |
Tip: don't mix manual versions with a BOM. If the BOM provides a version, don't override it without a reason — that's a source of classpath conflicts.
Maven for simplicity, Gradle for scale — both with a wrapper and consistent dependency management. We decide on the tool once per project and then stick to it consistently.