Adding Local JAR Dependencies in Maven and Packaging Strategies
When a project depends on JARs that are not available in a remote repository, you can bring them into a Maven build in two primary ways. The first publishes the artifact into your local repository and treats it like a normal dependency. The second wires the JAR directly via a system-scoped dependency and adjusts packaging to include it.
Option 1: Install the JAR into the Local Maven Repository
Use this when the third-party JAR is produced by a Maven build (or you can suppply metadata) and you want Mavan to manage it like any other dependency.
- Install the JAR into your local repo:
a: Install with explicit coordinates (and generate a POM if needed)
mvn install:install-file \
-Dfile=./libs/my-lib-1.2.3.jar \
-DgroupId=com.example.libs \
-DartifactId=my-lib \
-Dversion=1.2.3 \
-Dpackaging=jar \
-DgeneratePom=true
- Declare the dependency in your pom.xml:
<dependencies>
<dependency>
<groupId>com.example.libs</groupId>
<artifactId>my-lib</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
Maven will now resolve the atrifact from your local repository, and it will be handled like any other transitive dependency.
Option 2: Use a system-scoped dependency and point to a local file
Use this when the JAR cannot be (or should not be) published to a repository and you need to reference it directly from disk. You must then ensure it is packaged with your application and available on the runtime classpath.
- Add a system-scoped dependency that references the local file path:
<dependencies>
<dependency>
<groupId>com.vendor</groupId>
<artifactId>vendor-lib</artifactId>
<version>0.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/vendor/vendor-lib.jar</systemPath>
</dependency>
</dependencies>
- If you build a Spring Boot application, instruct the Spring Boot Maven Plugin to include system-scoped depandencies when creating the executable archive:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
- If you pacckage with the Maven JAR Plugin (non-Boot or plain JAR), add the system JAR to the manifest class path so it’s discoverable at runtime:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.example.app.Main</mainClass>
</manifest>
<manifestEntries>
<Class-Path>./lib/vendor-lib.jar</Class-Path>
</manifestEntries>
</archive>
<outputDirectory>${project.build.directory}/dist</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
- Example build section that separates the application JAR, libraries, and resources into a distribution layout:
<build>
<finalName>my-app</finalName>
<sourceDirectory>src/main/java</sourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<targetPath>${project.build.directory}/dist</targetPath>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<testSourceDirectory>src/test/java</testSourceDirectory>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
</testResources>
<plugins>
<!-- Include system-scope JARs when building a Spring Boot executable -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<!-- Copy all resolved dependencies (excluding systemPath unless included by plugin logic) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/dist/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- Create the application JAR with a manifest that points to libs/ -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.example.app.Main</mainClass>
</manifest>
<manifestEntries>
<!-- Explicitly include any system-scoped JARs that won’t be copied automatically -->
<Class-Path>./lib/vendor-lib.jar</Class-Path>
</manifestEntries>
</archive>
<outputDirectory>${project.build.directory}/dist</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>