Maven и локальные JAR: 5 фатальных ошибок и их решение

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему "просто скопировать JAR в папку" — не работает?

Каждый Java-разработчик, который хоть раз сталкивался с Maven, рано или поздно упирается в стену: "Мне нужно подключить старую библиотеку, которой нет в Maven Central. Что делать?". Вы гуглите, находите вопрос на Stack Overflow с тысячами просмотров, пробуете первый же совет — и получаете ClassNotFoundException или Missing artifact.

Знакомо? В этой статье мы разберём топ ошибок при добавлении локальных JAR файлов в Maven проект и, главное, как их избежать. Вы узнаете не только теорию, но и увидите рабочий код, который можно сразу применить в своём проекте на Java.

Ошибка №1: System scope без systemPath

Самая популярная ловушка новичков — добавить зависимость с <scope>system</scope>, но забыть указать <systemPath>. Maven честно пытается найти JAR, но не знает, где он лежит.

Как выглядит ошибка

[ERROR] Failed to execute goal on project my-app: 
Could not resolve dependencies for project com.example:my-app:jar:1.0: 
The following artifacts could not be resolved: 
com.example:my-custom-lib:jar:1.0 (absent)

Неправильный код

<dependency>
    <groupId>com.example</groupId>
    <artifactId>my-custom-lib</artifactId>
    <version>1.0</version>
    <scope>system</scope>
    <!-- systemPath отсутствует! -->
</dependency>

Правильное решение

Всегда указывайте полный путь к JAR-файлу через <systemPath>. Желательно использовать относительный путь от корня проекта, чтобы не привязываться к конкретной машине разработчика.

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

Важно: JAR-файл должен лежать в папке libs/ внутри вашего проекта. Создайте её, если ещё не сделали этого.

Ошибка №2: Забыли про install-file для многомодульных проектов

Допустим, вы добавили локальный JAR через system scope, и всё работает локально. Но когда вы пытаетесь собрать проект на CI-сервере (Jenkins, GitLab CI) — сборка падает. Почему? Потому что system scope не передаётся транзитивно и не попадает в локальный репозиторий Maven.

Правильный подход: установка JAR в локальный репозиторий

Используйте команду mvn install:install-file. Это добавит ваш JAR в ~/.m2/repository, и он будет доступен для всех модулей проекта и для CI-сборок.

mvn install:install-file \
   -Dfile=libs/my-custom-lib-1.0.jar \
   -DgroupId=com.example \
   -DartifactId=my-custom-lib \
   -Dversion=1.0 \
   -Dpackaging=jar \
   -DgeneratePom=true

После этого в pom.xml можно указывать обычную зависимость без systemPath:

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

Ошибка №3: Использование file:// URL в репозиториях

Некоторые разработчики пытаются "обмануть" Maven, добавляя локальную папку как репозиторий через <repository> с URL file://. Технически это работает, но создаёт кучу проблем:

  • Непереносимость: путь /home/user/project/libs не сработает на другой машине.
  • Путаница с версиями: Maven не проверяет метаданные, может подхватить старый JAR.
  • Проблемы с кэшированием: если вы обновили JAR, Maven может не заметить изменений.

Что делать вместо этого

Создайте локальный репозиторий внутри проекта (папка repo) и используйте mvn deploy:deploy-file для публикации JAR туда. Затем подключите этот репозиторий в pom.xml:

<repositories>
    <repository>
        <id>local-repo</id>
        <url>file://${project.basedir}/repo</url>
    </repository>
</repositories>

Этот подход гораздо чище, чем system scope, и легко делится через Git.

Ошибка №4: Игнорирование транзитивных зависимостей

Вы добавили локальный JAR, проект компилируется, но при запуске — NoClassDefFoundError. Скорее всего, ваш JAR сам зависит от других библиотек (например, Apache Commons или Log4j), и Maven об этом не знает.

Как это исправить

Есть три варианта:

  1. Вручную добавить все зависимости JAR в pom.xml (нужно знать, какие библиотеки использует JAR).
  2. Собрать "fat JAR" (uber-JAR) — один файл, содержащий все зависимости. Используйте плагин maven-shade-plugin.
  3. Создать POM-файл для вашего локального JAR с помощью install:install-file -DgeneratePom=true -DpomFile=path/to/pom.xml.

Пример создания POM для локального JAR:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>my-custom-lib</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>
    
    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>
    </dependencies>
</project>

Ошибка №5: Неправильная версия или groupId

Ка

Блоги

Рекомендаций по книгам