Stage 7: Tools and testing, lesson 1 of 7

Build tools: Maven and Gradle

Beginner3 min readall versions
Explain it forThe essentials plus production detail and pitfalls.

Real projects use a build tool to manage libraries and build steps.

Maven is configured in pom.xml:

  • Coordinates identify every library: groupId:artifactId:version.
  • Dependencies are downloaded from Maven Central into ~/.m2, along with the libraries they depend on.
  • Scopes: compile (the default), test, runtime and provided.
  • Lifecycle phases: validate, compile, test, package, verify, install. Running mvn package runs every phase before it.

Gradle uses a Kotlin or Groovy script (build.gradle.kts), is faster on large builds thanks to caching, and is the default for Android. Both use the same folder layout (src/main/java, src/test/java).

Use the wrapper scripts (./mvnw, ./gradlew) so everyone builds with the same tool version.

Example

Plain text
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.javaatlas</groupId>
  <artifactId>billing</artifactId>
  <version>1.0.0</version>

  <properties>
    <maven.compiler.release>25</maven.compiler.release>
  </properties>

  <dependencies>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.20.0</version>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>5.13.4</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>
Everyday commands
./mvnw clean package              # compile, test, build target/billing-1.0.0.jar
./mvnw test -Dtest=InvoiceTest    # run one test class
./mvnw dependency:tree            # every library and where it comes from
./gradlew build                   # the Gradle equivalent

Common mistake

Copying library JAR files into the project by hand instead of declaring dependencies. Builds break on other machines and upgrades become guesswork.

Under the hood

Version conflicts happen when two libraries need different versions of the same dependency: Maven picks the one nearest the top of the tree, Gradle the highest. Inspect with dependency:tree and pin versions with <dependencyManagement> or a BOM (Spring Boot's parent POM is one). Keep builds reproducible: commit the wrapper, avoid SNAPSHOT dependencies in releases, and let CI run the same command you run locally.

Check yourself

Which command builds a JAR with Maven?

How this connects

Part of Job-ready backend developer.

Was this lesson helpful?

Finished reading? Mark it complete to track your progress.