🛠️ Testing, Tools & Ecosystem · Advanced

Maven in Java

pom.xml, coordinates, lifecycle phases, dependency scopes.

🧩 The mysteryYour app uses 80 libraries. Nobody on the team downloaded a single JAR by hand, yet every build gets exactly the right versions. Meet the build tool behind half the Java world.

Declare, don't script

Maven builds a project from a declarative **pom.xml. Every artifact has coordinates: groupId:artifactId:version. Dependencies are downloaded from repositories into your local ~/.m2** cache.

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

The lifecycle

Builds run phases in a fixed order: validate, compile, test, package, verify, install, deploy. Running one phase runs all the phases before it. People skip running tests with -DskipTests.

mvn package   # validate+compile+test+package
mvn package -DskipTests
🔮 Predict it

Do the tests run?

You run mvn package. Do your unit tests run?

  1. Yes: test comes before package
  2. No: only packaging happens
  3. Only if you add -Dtest
Show the answer

Yes. Asking for package executes every earlier phase first, including compile and test.

Dependency scopes

compile (default): needed to compile and run, and passed on to consumers. provided: compile only; the server or JDK supplies it at runtime (the Servlet API). runtime: not for compiling, only for running (a JDBC driver). test: only for compiling and running tests.

⚠️ The trap

A test library in production

Mockito with compile scope lands on the main classpath and is passed on to everyone who depends on your service. Test libraries belong in **test** scope.

<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>5.12.0</version>
  <scope>compile</scope>  <!-- test! -->
</dependency>
🤔 Think first

install vs deploy

What's the difference between mvn install and mvn deploy?

Think about it, then reveal the answer

install copies the artifact into your **local ~/.m2 repository, so other builds on your machine can use it right away (Maven checks the local repository before going remote). deploy uploads it to a remote repository** for your team or the world.

💼 In the real world

Maven in CI

A typical CI job runs mvn verify: compile, all tests, plus integration checks, without installing anything. Releases run deploy to a company repository such as Nexus or Artifactory, or to Maven Central for open source.

Key takeaways

  1. Coordinates: groupId:artifactId:version
  2. mvn package also runs compile and test
  3. Scopes: compile (default), provided, runtime, test
  4. install = local ~/.m2; deploy = remote repository
🤯 Did you know?

Maven's default lifecycle has more than twenty phases; validate, compile, test, package, verify, install and deploy are just the famous ones.

Practice questions

What uniquely identifies a Maven artifact?

  1. The Java package name
  2. Its artifactId alone
  3. groupId:artifactId:version
  4. The JAR's file name
Check your answer

groupId:artifactId:version. The coordinate triple names an artifact in any repository. A packaging type and classifier can refine it further.

What's the difference between `mvn install` and `mvn deploy`?

  1. install downloads dependencies; deploy starts the app
  2. install runs tests; deploy skips them
  3. They're aliases
  4. install copies the artifact into your local ~/.m2 repository; deploy uploads it to a remote repository
Check your answer

install copies the artifact into your local ~/.m2 repository; deploy uploads it to a remote repository. install makes the artifact available to other builds on your machine; deploy shares it with your team or the world through a remote repository.

Maven describes your build in XML. Its main rival writes the build as code. Next: Gradle.