Java › Build Tools: Maven & Gradle
What is the difference between Maven's <dependencies> scope values (compile, provided, runtime, test) and how do they affect what's included in the final packaged artifact?
IntermediateAnswer
compile (the default) is available at both compile-time and runtime, and IS included in the final packaged artifact and propagated transitively; provided is available at compile-time but expected to be supplied by the runtime environment (like servlet-api when deploying to an app server that already provides it), so it's excluded from the final package; runtime is needed only at runtime, not compile-time (like a JDBC driver implementation used only through a generic interface), and IS included in the package; test is available only during test compilation/execution and never included in the final package at all.
<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope> <!-- servlet container already provides this at runtime -->
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope> <!-- only needed for running tests, excluded from the deployable WAR -->
</dependency>
</dependencies>Real-world example A WAR file deployed to an existing Tomcat server correctly excludes the servlet-api JAR (marked provided scope) from its packaged output, avoiding a classpath conflict with the version Tomcat itself already supplies, while still allowing the code to compile against those servlet APIs during the build.