Skip to content

Lesson 01 · Maven

Beyond the 1Z0-830 exam

Maven is the build tool these labs use — mvn -f labs/pom.xml test is how every example in this course is verified. Knowing the POM, the lifecycle, and dependency scopes is day-one developer knowledge, even though it's nowhere on the exam.

Objectives

After this lesson you will be able to:

  • Read a pom.xml: coordinates, dependencies, plugins, properties.
  • Explain the build lifecycle and why phases are cumulative.
  • Choose the right dependency scope and understand <scope>test</scope>.
  • Run and skip tests, and build a jar.

The POM and coordinates

A Maven project is described by a pom.xml. Every artifact is identified by three coordinates:

xml
<groupId>com.jse21</groupId>      <!-- who/namespace -->
<artifactId>jse21-labs</artifactId> <!-- the project name -->
<version>0.1.0</version>           <!-- this build's version -->

A dependency is just another artifact's coordinates:

xml
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter</artifactId>
  <version>5.11.3</version>
  <scope>test</scope>
</dependency>

Maven downloads it (and its transitive dependencies) from a repository — Maven Central by default — into your local ~/.m2/repository cache.

The build lifecycle and phases

The default lifecycle is an ordered list of phases. The common ones:

validate → compile → test → package → verify → install → deploy

The key rule: invoking a phase runs every phase before it. So mvn package first runs validate, compile, and test. You rarely call compile directly — you call the phase you want the result of.

CommandDoes
mvn compilecompile src/main/java
mvn testcompile + run unit tests (Surefire)
mvn packagethe above + build the jar into target/
mvn verify+ run integration tests / checks
mvn install+ copy the artifact into your local ~/.m2 cache
mvn cleandelete target/ (a different lifecycle, often chained: mvn clean test)

Gotcha

mvn test already compiled your code — there is no need to run mvn compile first. And mvn clean on its own only deletes target/; the build you want is usually mvn clean package.

Dependency scopes

Scope controls which classpath a dependency is on and whether it's packaged:

ScopeOn main classpath?On test classpath?Packaged?Example
compile (default)a library you call in src/main
testJUnit, Mockito, AssertJ
provided✅ (compile only)a servlet API supplied by the container
runtime❌ (compile) ✅ (run)a JDBC driver

test scope is why JUnit is available to your tests but doesn't leak into the shipped jar.

Plugins do the work

Phases are bound to plugin goals. The compiler plugin compiles; the Surefire plugin runs tests. This repo pins the Java release and the test runner:

xml
<properties>
  <maven.compiler.release>21</maven.compiler.release> <!-- compile to Java 21 even on a newer JDK -->
</properties>
<plugin>
  <artifactId>maven-surefire-plugin</artifactId>       <!-- runs JUnit tests in the test phase -->
  <version>3.5.2</version>
</plugin>

maven.compiler.release=21 is the modern replacement for separate source/target — it also prevents accidentally using APIs newer than Java 21.

Running the labs

bash
mvn -f labs/pom.xml test           # compile + run all lab tests
mvn -f labs/pom.xml test -Dtest=DesignTest   # one test class
mvn -f labs/pom.xml package -DskipTests       # build the jar, skip tests
mvn -f labs/pom.xml clean test     # fresh build

SDET note

-Dtest=... (Surefire) selects which tests run — handy for a fast local loop. In CI you'll instead use profiles or tags to split fast unit tests from slow integration tests (Modules 15 & 20), so the quick suite gates every push and the slow one runs less often.

Key Takeaways

  • An artifact = groupId:artifactId:version; dependencies are other artifacts, fetched from a repository (Maven Central) into ~/.m2.
  • Lifecycle phases are cumulative: mvn package runs validate→compile→test→package.
  • test scope = test classpath only, not packaged (JUnit, Mockito); runtime = needed to run but not compile (JDBC drivers).
  • Phases run plugin goals; pin Java with maven.compiler.release=21.
  • Run the labs with mvn -f labs/pom.xml test; -DskipTests to skip, -Dtest=Class to narrow.

Lesson Quiz

Lesson Quiz · Maven0 / 5
  1. What does `mvn package` execute before packaging?

    • ANothing — phases are independent
    • Bvalidate, compile, and test (all preceding phases)
    • COnly compile
    • Ddeploy
  2. JUnit is declared with <scope>test</scope>. What does that mean?

    • AIt's on the main and test classpaths and packaged
    • BIt's on the test classpath only and not packaged into the artifact
    • CIt's downloaded but never used
    • DIt's provided by the JDK
  3. Which three coordinates uniquely identify a Maven artifact?

    • Aname, author, license
    • BgroupId, artifactId, version
    • Cpackage, class, method
    • Drepo, branch, tag
  4. Why set maven.compiler.release=21?

    • AIt speeds up the build
    • BIt compiles to Java 21 bytecode AND rejects APIs newer than 21, even on a newer JDK
    • CIt is required for JUnit
    • DIt enables Gradle
  5. A JDBC driver is needed to run but not to compile your code. Best scope?

    • Acompile
    • Btest
    • Cprovided
    • Druntime

Next: Gradle (basics). This module's lab is in labs/src/main/java/com/jse21/m13_build/.