Appearance
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 → deployThe 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.
| Command | Does |
|---|---|
mvn compile | compile src/main/java |
mvn test | compile + run unit tests (Surefire) |
mvn package | the above + build the jar into target/ |
mvn verify | + run integration tests / checks |
mvn install | + copy the artifact into your local ~/.m2 cache |
mvn clean | delete 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:
| Scope | On main classpath? | On test classpath? | Packaged? | Example |
|---|---|---|---|---|
compile (default) | ✅ | ✅ | ✅ | a library you call in src/main |
test | ❌ | ✅ | ❌ | JUnit, 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 buildSDET 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 packagerunsvalidate→compile→test→package. testscope = 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;-DskipTeststo skip,-Dtest=Classto narrow.
Lesson Quiz
What does `mvn package` execute before packaging?
JUnit is declared with <scope>test</scope>. What does that mean?
Which three coordinates uniquely identify a Maven artifact?
Why set maven.compiler.release=21?
A JDBC driver is needed to run but not to compile your code. Best scope?
Next: Gradle (basics). This module's lab is in labs/src/main/java/com/jse21/m13_build/.