Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

To copy a Maven project’s runtime dependencies into target/lib during a normal build, bind the Apache Maven Dependency Plugin’s copy-dependencies goal to the package phase and set its output directory to ${project.build.directory}/lib. Run mvn clean package. The plugin copies selected dependency JARs; it does not, by itself, configure how Java launches your application.

Configure the plugin in your POM

Add this plugin under <project><build><plugins> in pom.xml. If your POM already has a <build> section, add the plugin to its existing <plugins> list rather than creating a duplicate section.

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <version>3.11.0</version>
      <executions>
        <execution>
          <id>copy-runtime-dependencies</id>
          <phase>package</phase>
          <goals>
            <goal>copy-dependencies</goal>
          </goals>
          <configuration>
            <outputDirectory>${project.build.directory}/lib</outputDirectory>
            <includeScope>runtime</includeScope>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

The Apache documentation lists version 3.11.0 for the Maven Dependency Plugin; pinning a version in the POM makes the build’s plugin choice explicit. See the goal documentation and the official copy-dependencies example.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • copy-dependencies copies dependency artifacts into a directory. It differs from dependency:copy, which copies one specified artifact, and dependency:unpack-dependencies, which extracts artifact contents.
  • ${project.build.directory} normally resolves to the project’s target directory. Using the property rather than hard-coding target respects a custom Maven build directory.
  • The package binding runs the copy when you invoke mvn package, and therefore also on later lifecycle commands such as mvn install and mvn deploy.
  • runtime selects runtime and compile dependencies, excluding provided and test-only dependencies. This is usually appropriate for an application distribution; omit the filter only when you intentionally want other scopes too.

Build and check the output

From the module directory containing this configuration, run:

mvn clean package

If the build succeeds and there are dependencies matching the configured filters, the module’s target directory should contain the application artifact and a lib directory. For example:

target/
├── example-app-1.0.0.jar
└── lib/
    ├── dependency-a-1.0.0.jar
    └── dependency-b-2.0.0.jar

On macOS or Linux, list the copied JARs with:

find target/lib -maxdepth 1 -type f -name '*.jar' -print

In Windows PowerShell, use:

Get-ChildItem targetlib -Filter *.jar

Copied files generally use Maven artifact names such as artifactId-version-classifier.extension; classifier and extension vary by artifact. The plugin usage documentation describes naming and filtering. A clean build is useful when checking output because clean removes the prior target directory before packaging.

Choose scopes and retain transitive dependencies deliberately

The includeScope value is a threshold, not a request to copy only dependencies whose declared scope exactly matches that word. The plugin documents these selections:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
includeScope Dependencies eligible for copying
runtime Runtime and compile
compile Compile, provided, and system
provided Provided
test All scopes
Empty or omitted All scopes

For a standalone application, runtime is a sensible starting point: test libraries are not normally shipped, while a provided dependency is expected from the runtime environment, such as an application server. That expectation may not fit your deployment, so check which APIs the target environment supplies. Maven scope alone cannot establish every runtime need, including native libraries, external services, or dynamically loaded classes.

Transitive dependencies are copied by default. Usually leave excludeTransitive unset; setting it to true limits copying to direct dependencies and can leave the application without libraries those dependencies require. Resolution and filtering still matter: declared exclusions, scope, classifiers, artifact types, and Maven’s dependency mediation affect what appears in the directory.

Make the copied JARs available to Java

Having JARs in target/lib does not make java -jar app.jar load them automatically. Use a launcher that supplies a classpath, or configure the application JAR’s manifest with an appropriate Class-Path. For example, when running from the project root:

# macOS or Linux
java -cp "target/example-app-1.0.0.jar:target/lib/*" com.example.Main
REM Windows Command Prompt
java -cp "targetexample-app-1.0.0.jar;targetlib*" com.example.Main

The Java launcher, not Maven, interprets the wildcard for JARs in lib. Classpath separators differ by operating system, so test the command or generated launcher on every supported platform. The main class and JAR name in these examples must match your project.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Filter, rename, or organize the copied files

Add these options inside the plugin execution’s <configuration> only when your distribution needs them. The goal’s supported parameters are documented in the copy-dependencies goal reference.

  • Select artifacts: <includeArtifactIds>slf4j-api,logback-classic,logback-core</includeArtifactIds> or <includeGroupIds>org.slf4j,ch.qos.logback</includeGroupIds>.
  • Exclude an artifact: <excludeArtifactIds>some-large-library</excludeArtifactIds>. Excluding a transitive library can cause runtime failures if another dependency needs it.
  • Restrict artifact types: <includeTypes>jar</includeTypes> limits eligible artifacts to JAR type. Use this only if your runtime does not need other artifact types.
  • Remove versions from filenames: <stripVersion>true</stripVersion> changes a name such as commons-lang3-3.17.0.jar to commons-lang3.jar. Prefer versioned names unless a deployment convention requires versionless files; versions aid identification and reduce collision risk.
  • Use nested directories: <useRepositoryLayout>true</useRepositoryLayout> creates repository-style group/artifact/version paths instead of a flat directory. <useSubDirectoryPerScope>true</useSubDirectoryPerScope> separates files by scope. These layouts do not suit a launcher expecting lib/*.

Troubleshoot missing or unexpected files

target/lib is absent

  • Confirm the execution is under <build><plugins>. A plugin declared only in <pluginManagement> is not automatically executed.
  • Check that the goal is copy-dependencies and that the build reaches the configured phase: run mvn package from the module with the execution.
  • Check whether any dependencies match the runtime scope and other filters. An empty selected set may leave no useful output.
  • Look for an overridden build directory or output-directory property. For diagnostic logging, run mvn package -X.

In a multi-module build, ${project.build.directory} is resolved separately for each project. A child module therefore normally writes to its own target/lib, not the reactor root’s directory.

Expected dependencies are missing

Check whether they are marked provided or test, excluded elsewhere in the dependency graph, a classifier variant, or intentionally supplied by the runtime platform. Confirm transitive copying has not been disabled. Inspect Maven’s runtime graph with:

mvn dependency:tree -Dverbose -Dscope=runtime

Compare that graph with the contents of target/lib, allowing for any configured filters.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Unwanted scopes or non-JAR files appear

Set <includeScope>runtime</includeScope> for a typical application bundle, and optionally <includeTypes>jar</includeTypes> if only JARs belong there. An empty includeScope makes all scopes eligible, so do not rely on it for a production directory unless that is intentional.

Files overwrite one another

Copying artifacts into one flat directory can overwrite files with identical names. Keep versioned filenames, avoid stripVersion, and inspect the resolved graph with mvn dependency:tree -Dverbose. Resolve duplicate or conflicting artifacts in the POM; if necessary, use per-artifact subdirectories and adjust the launcher to match.

The app reports ClassNotFoundException

First check the launch classpath: the files may have copied correctly but not been included at runtime. Launch with a classpath covering both the application JAR and the dependency directory, or provide the equivalent manifest or script configuration.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When a different packaging method fits better

Packaging choice Use it when Important trade-off
Separate JARs in lib Your deployment expects an application JAR beside dependencies, or operators need to inspect individual libraries. You must provide and test a classpath or launcher; distribution includes multiple files and classpath ordering can matter.
Shade Plugin You need a single bundled JAR, package relocation, or control over merged resources. Resources such as META-INF/services may need transformers. Minimization can remove classes used through reflection or dynamic loading. See the Shade usage guide and goal reference.
Assembly Plugin You need a ZIP/TAR distribution containing directories such as bin, conf, and lib. A custom descriptor offers control over layout. The predefined jar-with-dependencies creates a combined JAR; the Assembly documentation recommends Shade when more control over a combined JAR is needed. See descriptor references and assembly components.

Copy dependencies when your deployment genuinely expects separate files in a library directory. If using a framework with its own packaging convention, follow that framework’s packaging model rather than assuming a generic target/lib layout is appropriate.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Release-build checklist

  • Pin the Dependency Plugin version and bind copy-dependencies to package.
  • Use the intended scope and retain transitive dependencies unless you have a reason not to.
  • Build from the correct module, inspect the generated files, and test the actual launcher on supported operating systems.
  • Check for filename collisions and confirm the target environment supplies dependencies intentionally omitted as provided.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.