Question

How to Add Local JAR Files to a Maven Project in Java

javamavendependencieslibrariesmvn-repo

Question

I want to use local JAR files in a Maven project, but those JARs are not available in any Maven repository yet. How can I include them in my project so Maven can compile and run the application correctly?

Short Answer

By the end of this page, you will understand how Maven handles dependencies, why local JAR files are a special case, and the common ways to use them in a Java project. You will also learn which approach is best for short-term use and which one is better for real projects.

Concept

Maven manages project dependencies using coordinates such as groupId, artifactId, and version. Normally, Maven downloads libraries from remote repositories like Maven Central, or from your local Maven cache.

A local JAR file becomes a problem when it is not published anywhere Maven can find it. In that case, Maven does not automatically know:

  • what the library is called
  • what version it is
  • where to download it from

There are two main ways developers deal with this:

  1. Reference the JAR directly from the filesystem using system scope
  2. Install the JAR into the local Maven repository so Maven can treat it like a normal dependency

The second option is usually better because it fits Maven's dependency system.

Why this matters:

  • builds become more repeatable
  • dependency management stays consistent
  • IDE support works better
  • CI/CD pipelines are easier to set up later

Using random JAR files copied into a project can work temporarily, but it usually causes problems for teammates and build servers if not handled carefully.

Mental Model

Think of Maven as a librarian.

Normally, you ask for a book using a catalog entry:

  • groupId = section of the library
  • artifactId = book title
  • version = edition

Maven then goes to the shelf or orders the book from another library.

A local JAR file is like having a book that is not in the catalog. You have two choices:

  • Point directly to the physical book on your desk using a file path
  • Add the book to the catalog first so the librarian can manage it properly

The second option is cleaner, more organized, and works better when other people need the same book.

Take Quiz

Syntax and Examples

Option 1: Directly reference a local JAR with system scope

This approach points to a JAR file on disk.

<dependency>
  <groupId>com.example</groupId>
  <artifactId>my-local-lib</artifactId>
  <version>1.0.0</version>
  <scope>system</scope>
  <systemPath>${project.basedir}/lib/my-local-lib-1.0.0.jar</systemPath>
</dependency>

Example project structure:

my-app/
├── pom.xml
├── lib/
│   └── my-local-lib-1.0.0.jar
└── src/

Important note

This works, but system scope is generally discouraged because:

  • the dependency is not resolved like normal Maven dependencies
  • it does not behave well in shared builds
  • some tools and plugins may not handle it consistently

Option 2: Install the JAR into your local Maven repository

This is the preferred approach for local development.

Run this command:

mvn install:install-file \
  -Dfile=lib/my-local-lib-1.0.0.jar \
  -DgroupId=com.example \
  -DartifactId=my-local-lib \
  -Dversion=1.0.0 \
  -Dpackaging=jar

After that, declare it like a normal dependency in pom.xml:

<dependency>
  <groupId>com.example</groupId>
  <artifactId>my-local-lib</artifactId>
  <version>1.0.0</version>
</dependency>

This makes Maven treat the JAR more like a real managed dependency.

Example Java usage

import com.example.lib.Utility;

public class Main {
    public static void main(String[] args) {
        System.out.println(Utility.getMessage());
    }
}

If the JAR is correctly available to Maven, your code can import and use its classes normally.

Step by Step Execution

Consider this setup:

mvn install:install-file \
  -Dfile=lib/my-local-lib-1.0.0.jar \
  -DgroupId=com.example \
  -DartifactId=my-local-lib \
  -Dversion=1.0.0 \
  -Dpackaging=jar

And this dependency:

<dependency>
  <groupId>com.example</groupId>
  <artifactId>my-local-lib</artifactId>
  <version>1.0.0</version>
</dependency>

What happens step by step:

  1. Maven reads the install:install-file command.
  2. It takes the physical file at lib/my-local-lib-1.0.0.jar.
  3. It stores that file in your local Maven repository, usually under a path like:
~/.m2/repository/com/example/my-local-lib/1.0.0/
  1. Maven associates that file with these coordinates:
    • groupId: com.example
    • artifactId: my-local-lib
    • version: 1.0.0
  2. Later, when you run mvn compile or open the project in your IDE, Maven reads pom.xml.
  3. Maven looks for com.example:my-local-lib:1.0.0 in the local repository.
  4. Since the JAR is now installed there, Maven resolves it successfully.
  5. Your Java compiler can now find classes from that JAR.

Small trace example

pom.xml:

<dependencies>
  <dependency>
    <groupId>com.example</groupId>
    <artifactId>my-local-lib</artifactId>
    <version>1.0.0</version>
  </dependency>
</dependencies>

Main.java:

import com.example.lib.Utility;

public class Main {
    public static void main(String[] args) {
        String message = Utility.getMessage();
        System.out.println(message);
    }
}

Execution flow:

  • Maven resolves my-local-lib
  • Java compiles Main.java
  • Utility is found inside the installed JAR
  • The program runs successfully

Real World Use Cases

Local JAR handling appears in several real situations:

  • Internal company libraries not yet published to Artifactory, Nexus, or Maven Central
  • Vendor SDKs distributed only as downloadable JAR files
  • Legacy systems where dependencies are shared manually
  • Prototype projects that depend on a library still under development
  • Offline environments where developers cannot access remote repositories

Example scenarios:

  • A payment hardware vendor gives your team terminal-sdk.jar
  • A legacy reporting tool depends on old-report-engine.jar
  • Another internal team sends you a test build of custom-auth-lib.jar

In each case, Maven still needs a way to identify and resolve that JAR consistently.

Take Quiz

Real Codebase Usage

In real projects, developers usually avoid committing unmanaged JAR files directly unless there is no better option.

Common patterns include:

Installing once into the local repository

A developer runs:

mvn install:install-file -Dfile=vendor-sdk.jar -DgroupId=com.vendor -DartifactId=sdk -Dversion=2.1.0 -Dpackaging=jar

Then the project uses a normal dependency declaration.

Publishing to a private repository

In team environments, the better long-term solution is to publish the JAR to:

  • Nexus
  • Artifactory
  • GitHub Packages
  • an internal Maven repository

That way everyone gets the same dependency without manual setup.

Using guardrails in documentation

Teams often add setup instructions in:

  • README.md
  • onboarding docs
  • build scripts

Example note:

Before building, install vendor-sdk-2.1.0.jar into your local Maven repository.

Validation and build consistency

Developers try to avoid hidden machine-specific paths such as:

<systemPath>C:/Users/Alice/Desktop/sdk.jar</systemPath>

These paths break on other machines.

Early migration to proper repository management

If a local JAR becomes important, teams usually move it into a proper repository quickly. That reduces:

  • setup friction
  • version confusion
  • CI failures
  • "works on my machine" problems

Common Mistakes

1. Using an absolute file path

Broken example:

<systemPath>C:/Users/John/libs/tool.jar</systemPath>

Why it is a problem:

  • only works on one machine
  • breaks for teammates and CI

Safer version:

<systemPath>${project.basedir}/lib/tool.jar</systemPath>

Even better: install the JAR into the local Maven repository.

2. Forgetting system scope when using systemPath

Broken example:

<dependency>
  <groupId>com.example</groupId>
  <artifactId>tool</artifactId>
  <version>1.0</version>
  <systemPath>${project.basedir}/lib/tool.jar</systemPath>
</dependency>

Problem:

  • systemPath requires scope to be system

Fixed version:

<dependency>
  <groupId>com.example</groupId>
  <artifactId>tool</artifactId>
  <version>1.0</version>
  <scope>system</scope>
  <systemPath>${project.basedir}/lib/tool.jar</systemPath>
</dependency>

3. Assuming other developers already have the JAR

If you install a JAR only on your own machine, your teammates and CI server will not have it automatically.

Avoid this by:

  • documenting the setup steps
  • using a shared repository when possible

4. Using inconsistent coordinates

If you install a file with one set of coordinates:

-DgroupId=com.example -DartifactId=tool -Dversion=1.0

but declare another in pom.xml:

<groupId>com.example.libs</groupId>
<artifactId>toolkit</artifactId>
<version>1.0</version>

Maven will not find the dependency.

5. Treating system scope as a long-term solution

It may work for quick tests, but it is not ideal for maintainable builds.

Prefer:

  • local repository installation for temporary use
  • private repository publishing for team use

Comparisons

ApproachHow it worksProsConsBest use
system scope + systemPathPoints directly to a JAR file in the filesystemQuick to set upDiscouraged, machine-dependent, weaker Maven integrationTemporary local experiments
mvn install:install-fileInstalls the JAR into your local Maven repositoryWorks like a normal dependency afterwardMust be repeated on each machineShort-term local development
Private Maven repositoryPublishes the JAR to a shared repositoryBest for teams, CI, versioning, repeatable buildsRequires repository setupReal projects and shared codebases

system scope vs installed dependency

  • system scope: Maven is told exactly where the file is
  • Installed dependency: Maven resolves the file using coordinates from its repository system

Local repository vs remote/private repository

  • Local repository: only your machine has the JAR
  • Private repository: your whole team and build servers can access it
Take Quiz

Cheat Sheet

Quick reference

Direct local JAR reference

<dependency>
  <groupId>com.example</groupId>
  <artifactId>my-lib</artifactId>
  <version>1.0.0</version>
  <scope>system</scope>
  <systemPath>${project.basedir}/lib/my-lib.jar</systemPath>
</dependency>

Install JAR into local Maven repository

mvn install:install-file \
  -Dfile=lib/my-lib.jar \
  -DgroupId=com.example \
  -DartifactId=my-lib \
  -Dversion=1.0.0 \
  -Dpackaging=jar

Normal dependency after installation

<dependency>
  <groupId>com.example</groupId>
  <artifactId>my-lib</artifactId>
  <version>1.0.0</version>
</dependency>

Rules to remember

  • Prefer installing the JAR instead of using system scope
  • Keep groupId, artifactId, and version consistent
  • Avoid absolute paths in systemPath
  • Local installation helps only your machine
  • For teams, use a private Maven repository

Edge cases

  • If the JAR has transitive dependencies, manual local handling may not include them automatically
  • If the version changes, update both the installed artifact and pom.xml
  • If Maven cannot resolve the dependency, check the coordinates carefully

FAQ

Can I put a JAR inside my project and reference it directly in Maven?

Yes. You can use system scope with systemPath, but this is generally discouraged for long-term use.

What is the best way to use a local JAR in Maven?

Usually, install it into your local Maven repository with mvn install:install-file, then reference it like a normal dependency.

Why does Maven not recognize my local JAR automatically?

Maven resolves dependencies by coordinates and repositories, not by scanning random files in your project.

Will mvn install:install-file make the JAR available to my teammates?

No. It installs the JAR only on your machine. Teammates must install it too, or you should publish it to a shared repository.

Is system scope deprecated or discouraged?

It is widely discouraged in modern Maven usage because it bypasses normal dependency management.

Where does Maven store locally installed JAR files?

Usually in the local repository under ~/.m2/repository.

What if the local JAR changes?

You should reinstall the updated JAR and make sure the versioning stays clear and consistent.

Take Quiz

Mini Project

Description

Create a small Java Maven project that uses a custom local JAR file. This project demonstrates both the Maven dependency declaration and how a class from the JAR becomes available in application code.

Goal

Set up a Maven project that successfully imports and uses a class from a local JAR installed into the Maven local repository.

Requirements

  1. Create a Maven project with a pom.xml file.
  2. Install a local JAR into your Maven local repository using mvn install:install-file.
  3. Add the matching dependency to pom.xml.
  4. Write a Main class that calls a method from the JAR.
  5. Run the project and confirm the external class is resolved.
Take Quiz

Keep learning

Related questions

View more