Dependency Scope
About
In Maven, dependency scopes define the visibility and lifecycle of a dependency. The scope of a dependency determines where it is available in the project lifecycle (compile, test, runtime, etc.) and whether it is included in the final package. Here are the different types of dependency scopes in Maven.
Maven dependency scope defines when and where a dependency is required in a project. It controls:
Availability of dependencies at compile-time, test-time, runtime, or packaging.
Inclusion of dependencies in the final artifact.
Propagation of dependencies to dependent projects (transitive dependencies).
Maven has six dependency scopes -
Scope
Used for
Available at Compile?
Available at Runtime?
Inherited by Child Projects?
Packaged in WAR/JAR?
compile
Default scope (for APIs)
Yes
Yes
Yes
Yes
provided
Dependencies available at runtime (like Java EE APIs, servlet APIs)
Yes
No
Yes
No
runtime
Needed at runtime, but not at compile-time (e.g., JDBC drivers)
No
Yes
Yes
Yes
test
Only required for testing (JUnit, Mockito, etc.)
No
Yes (Test phase only)
No
No
system
Similar to provided
, but requires an absolute path to a local JAR
Yes
Yes
Yes
No
import
Used with dependencyManagement
in multi-module projects
No
No
Yes
No
1. compile
compile
Default Scope: If no scope is specified, the dependency is assumed to be in the
compile
scope.Availability: Available in all classpaths (compilation, testing, runtime, and packaged in the final artifact).
Use Case: For dependencies required for the project to compile, such as the main application libraries.
2. provided
provided
Similar to
compile
, but not packaged in the final artifact.Availability: Available in the compilation and test classpaths but not in the runtime classpath.
Use Case: For dependencies provided by the runtime environment (e.g., a servlet API provided by the application server). For eg, we are deploying to an application server like Tomcat, WildFly, or GlassFish, which already provides the required JARs.
3. runtime
runtime
Availability: Available in the runtime and test classpaths but not in the compilation classpath.
Use Case: For dependencies required only at runtime, such as JDBC drivers.
Helps reduce unnecessary dependencies during compilation.
4. test
test
Availability: Available only in the test classpath. Dependencies required only for testing.
Use Case: For dependencies needed only for testing purposes, such as testing frameworks (e.g., JUnit). Typically used for JUnit, Mockito, TestNG, etc.
5. system
(Rarely Used)
system
(Rarely Used)Availability: Similar to
provided
, but the JAR file for the dependency must be explicitly provided and not downloaded from a repository.Use Case: For dependencies that must be explicitly specified and are not available in any remote repository. Useful when we have proprietary JARs that are not available in public repositories.
Additional Requirement: Requires the
systemPath
element to specify the path to the JAR file.
6. import
(Used in Multi-Module Projects)
import
(Used in Multi-Module Projects)Availability: Not a regular dependency, but rather a way to manage dependencies. Only used in the
<dependencyManagement>
section.Use Case: Used to import dependencies from a BOM (Bill of Materials) POM. Managing dependency versions centrally in a parent POM.
How Dependency Scope Affects Transitive Dependencies ?
Maven automatically propagates dependencies (also known as transitive dependencies) based on the scope of the parent dependency. However, the scope of a transitive dependency may change depending on the scope of the dependency that introduced it.
Propagation Rules for Transitive Dependencies
Compile Scope: If a dependency is declared with
compile
, its transitive dependencies are also available withcompile
scope in dependent projects.Provided Scope: Dependencies declared with
provided
scope do not propagate transitively.Runtime Scope: If a dependency is declared with
runtime
, its transitive dependencies are only available at runtime (not at compile-time).Test Scope: Dependencies with
test
scope are not propagated transitively. They are only available in the module where they are declared.System Scope: Dependencies with
system
scope are not propagated at all.Import Scope: Used for dependencyManagement in parent POMs, it does not propagate dependencies directly.
Example: How Scope Affects Transitive Dependencies
Consider the following scenario:
Dependency Hierarchy
Project A depends on Library B with
compile
scope.Library B depends on Library C with
runtime
scope.Project A will get:
Library B with
compile
scope.Library C with runtime scope (because transitive dependencies inherit their scope from their parent).
Transitive Scope Propagation
Parent Dependency Scope
Transitive Dependencies' Scope in Child Modules
compile
compile (default behavior)
provided
Not propagated
runtime
runtime (not available at compile-time)
test
Not propagated (only for the current module)
system
Not propagated (requires manual JAR inclusion)
import
Not propagated (only for dependency management)
Overriding Transitive Dependency Scope
We can override transitive dependency scopes by re-declaring the dependency with a different scope.
Example:
If this was originally a runtime
dependency, we force it to be compile
.
Optimizing Dependencies Using Dependency Analysis Plugin
Use this plugin to check unused dependencies:
It will report unnecessary dependencies or those with incorrect scopes.
Example
1. Compile Scope (Default)
Example: Spring Boot Core Dependencies
Scenario: A Spring Boot web application needs spring-web
at compile-time and runtime.
Why compile
?
Needed during development for writing controllers and services.
Required at runtime for handling HTTP requests.
Included in the final JAR/WAR file.
2. Provided Scope
Example: Servlet API in a Web Application
Scenario: A Java web application runs on Tomcat, which already provides the Servlet API.
Why provided
?
The Servlet API is already available in Tomcat at runtime.
Avoids duplicate dependencies in the final JAR/WAR.
Available at compile-time, but not included in the final package.
What happens if we use compile
instead?
The Servlet API JAR will be included in our WAR, leading to conflicts when deployed in Tomcat.
3. Runtime Scope
Example: JDBC Driver
Scenario: Our application connects to MySQL, but the MySQL driver is only needed at runtime, not at compile-time.
Why runtime
?
Not needed at compile-time because we use JDBC interfaces (
java.sql.Connection
).Required at runtime when the app connects to MySQL.
Included in the final JAR/WAR.
What happens if we use compile
instead?
The MySQL driver will be available at compile-time, even though we only need it at runtime.
4. Test Scope
Example: JUnit & Mockito for Testing
Scenario: Our application needs JUnit and Mockito for unit testing, but these should not be included in production.
Why test
?
JUnit and Mockito are only needed for testing, so they should not be packaged in the final artifact.
Reduces bloat in the final build.
Available only during test compilation and execution.
What happens if we use compile
instead?
The testing libraries would be included in the production JAR, which is unnecessary.
5. System Scope
Example: Proprietary JAR
Scenario: Our project uses a custom in-house library (custom-lib.jar
) that is not available in any Maven repository.
Why system
?
The JAR is not in Maven Central or a private repo.
Ensures that a specific version of
custom-lib.jar
is always used.
Why is system
not recommended?
Hardcodes file paths, making the project non-portable.
Better alternative: Upload the JAR to a private Nexus/Artifactory repository.
Better approach: Deploy the JAR to a local Maven repo
Then use:
6. Import Scope (Multi-Module Projects)
Example: Spring Boot Dependency Management
Scenario: A multi-module Maven project needs to share dependencies across multiple submodules.
In the parent pom.xml
:
Why import
?
Ensures all submodules use the same dependency versions.
Prevents version mismatches across modules.
What happens if we don’t use import
?
Each submodule might have different versions of dependencies, causing conflicts.
Last updated
Was this helpful?