Start with a basic pom.xml that declares several libraries:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.16.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Copying Individual Artifacts
The copy goal fetches specific artifacts regardless of whether they appear in the project's dependency list. In this configuration, the plugin retrieves Jackson Databind into a dedicated folder:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<id>fetch-jackson</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/external-libs</outputDirectory>
<destFileName>jackson-custom.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</plugin>
Execute either mvn dependency:copy or mvn package. The artifact lands in target/external-libs as jackson-custom.jar. Omitting destFileName preserves the original filename including its version. When the artifact is already a declared dependency, the version element inside artifactItem can be left out.
Collecting All Runtime Dependencies
To assemble every project dependency into one location, bind the copy-dependencies goal to the lifecycle:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<id>distribute-deps</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/distribution/lib</outputDirectory>
<excludeTransitive>false</excludeTransitive>
<stripVersion>true</stripVersion>
<excludeArtifactIds>lombok,commons-codec</excludeArtifactIds>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
Running mvn package produces target/distribution/lib containing the collected JARs.
Key parameters:
excludeTransitive: Set totrueto skip transitive artifacts. Typicallyfalseis desired so that indirect requirements are included.stripVersion: Whentrue, filenames exclude version segments.excludeArtifactIds: Comma-separated list of artifacts to omit.includeScope: Restricts collection to dependencies matching the given scope, such asruntimeorcompile.
Extracting a Specific Archive
Use the unpack goal to explode a single artifact and merge its contents into the build:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<id>extract-classes</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<includes>**/*.class,**/*.properties</includes>
<excludes>**/*Test*.class</excludes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
During prepare-package, the specified archive is decompressed into target/classes, making its contents available in the final artifact.
Unpacking the Entire Dependency Set
The unpack-dependencies goal operates on the full dependency graph. This is functionally comparable to assembly or shading strategies:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<id>inline-deps</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includes>**/*.class</includes>
<excludes>**/*.xml</excludes>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
All dependency classes are extracted into the build output directory, producing an uber-like structure without using a dedicated shade plugin.
Fetching Source Code Archives
Attaching the sources classifier retrieves corresponding source JARs instead of compiled binaries:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<id>pull-sources</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<classifier>sources</classifier>
<failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
<outputDirectory>${project.build.directory}/src-deps</outputDirectory>
<includeArtifactIds>commons-lang3,commons-codec</includeArtifactIds>
</configuration>
</execution>
</executions>
</plugin>
This downloads and unpacks the source bundles for the filtered artifacts into target/src-deps.
Analyzing Dependency Usage
The analyze-only goal inspects the POM for missing or superfluous declarations. Bind it to the lifecycle like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<id>check-dependency-health</id>
<goals>
<goal>analyze-only</goal>
</goals>
<configuration>
<failOnWarning>true</failOnWarning>
<ignoredDependencies>
<ignoredDependency>com.google.errorprone:error_prone_annotations</ignoredDependency>
</ignoredDependencies>
<ignoredUsedUndeclaredDependencies>
<ignoredUsedUndeclaredDependency>org.slf4j:slf4j-api</ignoredUsedUndeclaredDependency>
</ignoredUsedUndeclaredDependencies>
<ignoredUnusedDeclaredDependencies>
<ignoredUnusedDeclaredDependency>org.projectlombok:lombok</ignoredUnusedDeclaredDependency>
</ignoredUnusedDeclaredDependencies>
</configuration>
</execution>
</executions>
</plugin>
Invoking mvn dependency:analyze produces output categorizing artifacts as used-but-undeclared, unused-but-declared, or non-test-scoped issues. The plugin can be configured to fail the build when such warnings are detected.
Visualizing the Dependency Graph
The tree goal renders the transitive hierarchy without modifying build output:
mvn dependency:tree
For large projects, redirect the output to a file:
mvn dependency:tree -DoutputFile=dependencies.txt
Filter the graph to show only selected coordinates:
mvn dependency:tree -Dincludes=org.springframework.boot:spring-boot-starter-web,org.apache.commons:commons-lang3
Conversely, exclude specific subtrees from the output:
mvn dependency:tree -Dexcludes=org.apache.logging.log4j:*