Как подключить зависимости в maven
Как с помощью maven работать с библиотеками, которых в maven нет
В статье я расскажу, как подключить библиотеку, которой в maven по умолчанию нет, и как подключить другую библиотеку, исходники которой давным-давно потеряны.
Также я опишу, как сделать maven проект, который генерирует артефакт, по совместительству являющийся библиотекой, и как подключить эту библиотеку к другому своему же maven проекту.
Эта статья для тех, кто только начинает осваивать java.
В моей предыдущей статье было сказано, что maven сам скачает все указанные в pom.xml зависимости. А вот что будет, если он какую-нибудь зависимость не найдёт? В таком случае maven скажет, что зависимость не обнаружена и прервёт процесс сборки с ошибкой. Что делать в этом случае?
Этот вопрос, на самом деле, распадается на несколько вопросов, каждый из которых надо решать индивидуально. Выбор решения же определяется тем, где эта зависимость есть.
Зависимость может быть в интернете в каком-то месте, о существовании которого maven не знает. Ещё она может быть в виде jar файла у вас на руках и, наконец, в виде исходного кода, оформленного как maven проект.
Об этих трёх случаях мы и поговорим.
Но сначала надо коротко прояснить один вопрос.
Откуда maven качает библиотеки
На просторах интернета есть сервер, на котором выложены java библиотеки. Этот сервер называется репозиторием, а по-русски — хранилищем. Это не какой-то абстрактный, а вполне конкретный ресурс, адрес которого зашит в дефолтные настройки maven. Поэтому он называется репозиторием по умолчанию. Именно там maven будет искать зависимости из pom.xml.
Как быть, если библиотеки нет в удалённом хранилище по умолчанию, но она есть в другом удалённом хранилище
Первая и, возможно, самая частая проблема возникает, если библиотеки в этом умолчальном репозитории нет или в случае, если этот репозиторий с машины, на которой осуществляется сборка, недоступен, например, по соображениям безопасности.
Причины проблемы немного разные, но решение одинаковое — нужно указать репозиторий, в котором зависимости есть. Это либо какой-то другой адрес в Интернете, либо адрес репозитория, поднятого админами в локальной сети.
Как указать maven проекту, где искать дополнительный репозиторий
Для того, чтобы указать maven, что зависимости надо искать не только в умолчальном репозитории, существует штатный механизм. Вот так можно прописать ещё один адрес для поиска.
Далее мы подключили репозиторий проекта Spring, в котором можно найти последние версии этого семейства бибилиотек. Вот как это выглядит внутри pom.xml
Теперь maven, когда не найдёт зависимости в репозитории по умолчанию, или обнаружит, что оный недоступен — не запаникует, а поищет библиотеку в ещё одном репозитории и, если всё идёт по плану, найдёт её там. Тут следует уточнить, что если ваша программа может быть использована в качестве зависимости, например, если сама является библиотекой, то класть тег репозиторий в pom.xml — не лучшая идея. Объяснение того, почему это так, выходит за рамки статьи, но с ним можно ознакомиться тут.
Но бывает так, что библиотеки в репозиториях нет. Например, если это драйвера для MSSQL, или если это проприетарная библиотека, которую вы недавно приобрели за большие деньги.
Как подключить библиотеку, которой в репозиториях нет
Подключить такую библиотеку можно несколькими способами. Например, если у вас есть свой репозиторий в локальной сети, то можно (а иногда даже нужно), положить библиотеку туда, и тем самым свести задачу к предыдущей.
Но, если это возможно, такую библиотеку лучше положить в проект и хранить прямо в системе контроля версий. Тогда библиотека будет доступна программе всегда и на любой машине, а шаг по копированию этой библиотеки в репозиторий можно не включать в мануал.
Для обработки таких кейсов у maven тоже есть штатный механизм. Только что мы выяснили, как указать maven удалённый репозиторий, отличный от умолчального. Так вот, не обязательно использовать удалённое хранилище. Можно сделать репозиторий в локальной файловой системе, положить туда библиотеку и проинструктировать maven искать зависимости ещё и там.
Как создать свой локальный репозиторий
Для этого, как сказано выше, у maven есть штатное средство.
Допустим у нас есть библиотека, которая находится в jar файле под названием hello-world-library-1.0-SNAPSHOT.jar. О библиотеке нам известно, что в ней есть один класс HelloWorld, который включает один статический метод say, печатающий в консоли, как несложно догадаться, Hello World.
Мы хотим в директории проекта создать директорию lib, в которой будет находиться наш дополнительный репозиторий, и поместить туда библиотеку. Для этого достаточно в директории проекта выполнить следующую команду.
Если вы используете операционную систему Windows, нужно заменить \ на ^, то есть написать
Или можно просто убрать \ и написать команду в одну строчку.
Обратите внимание, как и для любого другого артефакта, для библиотеки нам нужно придумать groupId, artifactId и version. Мы потом укажем их в pom.xml, когда будем подключать зависимость.
Внутри директории, которую создаст команда, находится полноценный репозиторий, для использования которого достаточно указать maven, где он находится. Все сведения о том, какие библиотеки можно там найти, содержатся непосредственно в структуре директорий свежесозданного репозитория. Для последующего использования репозитория, например, на других машинах, команду deploy-file выполнять не надо.
Дать проекту знать, что репозиторий существует, и показать, где он находится, можно уже описанным способом, правда, с поправкой на то, что репозиторий локальный.
Обратите внимание на пятую строку
Тут сказано, что искать репозиторий надо в директории проекта, на которую указывает встроенная переменная maven project.basedir.
Класс, использующий библиотеку, будет предельно прост, но для порядка приведём его код.
Осталось добавить в pom.xml зависимость и можно собирать проект.
Директорию lib надо закомитить и библиотека будет доступна проекту вообще всегда.
Однако следует помнить об одном правиле.
Нужно обязательно обновлять номер версии библиотеки в локальном репозитории при каждом изменении jar файла
Maven воспринимает репозитории как внешние, поэтому, если не изменить номер версии, то maven будет использовать не версию библиотеки из директории lib, а ту, что он закешировал на локальной машине. В данном конкретном случае это не должно сыграть роли из-за суффикса SNAPSHOT, но об этом нужно знать.
Есть ещё один распространённый сценарий. У вас есть своя библиотека, которую вы сами собираете с помощью maven и потом подключаете к другому maven проекту.
Как сделать свою java библиотеку
Для того, чтобы сделать библиотеку, достаточно написать класс с модификатором public. И потом можно будет использовать этот класс в коде, к которому подключена библиотека.
Вот такой, например, класс.
Теперь нужно сделать maven проект, который будет собирать библиотеку, содержащую этот класс.
Как мы помним, с точки зрения maven, библиотека — это просто артефакт, поэтому помник будет выглядеть тривиально.
Итак, у нас есть класс со статическим методом, у нас есть описание артефакта для maven. Осталось только собрать этот код, чтобы получилась библиотека, то есть jar файл.
Просто напишем в консоли:
Как подключить свежесозданную библиотеку к своему maven проекту
Для того, чтобы библиотеку потом можно было подключать к другому проекту, нужно вместо package написать install.
Это нужно будет делать после каждого изменения в коде библиотеки, и на каждом компьютере, на котором мы захотим эту библиотеку использовать.
Теперь можно сделать новый проект, который будет использовать библиотеку.
Внутри проекта будет один класс, который использует статический метод из библиотеки, чтобы сказать Hello world. Мы этот класс уже видели.
Работает не хуже предыдущего варианта!
Что если ваша библиотека использует другую библиотеку?
Вопрос, казалось бы, глупый, но на всякий случай проведём эксперимент.
Сделаем библиотеку с непустыми зависимостями.
и напишем для неё код
Перейдём в директорию с нашим проектом, который эту библиотеку использует и попробуем его собрать и запустить.
Как это работает
Строго говоря знать, как процесс устроен внутри, не обязательно, но всё равно очень полезно.
Команда mvn install соберёт библиотеку, а потом положит её в локальный репозиторий по умолчанию. То есть в то же самое место, где лежат все библиотеки, которые вы когда-либо подключали к maven проектам, за исключением, разумеется, тех, которые находятся в локальных репозиториях, сделанных лично вами.
Потом, при сборке проекта, использующего эту библиотеку, maven поищет её в локальном хранилище, найдёт и подключит.
Итого
UPD: В комментариях sshikov, igor_suhorukov, jbaruch и другие высказали мнение, что библиотеки нельзя хранить вместе с исходниками, потому что для этого есть другие, предназначенные специально для этого инструменты, такие как Nexus и Artifactory.
Тут я совершенно согласен. Когда речь идёт о крупных проектах и корпоративной разработке, быть по-другому просто не может. Но, с моей точки зрения, есть случаи, когда удобнее сделать иначе. Я имею в виду маленькие проекты, созданные в процессе обучения, потому что именно с такими вещами обычно имеют дело новички, и случаи, когда доступа к инфраструктуре нет, а добавить библиотеку в сборку нужно в течение 10 минут. Нужно было с самого начала уточнить, что речь в статье именно о таких кейсах.
Да, хранить библиотеки в системе контроля версий — хак. Но, как и все хаки, это такая штука, которой в некоторых случаях можно пользоваться и о возможности осуществления которой неплохо бы знать.
Причины, по которым техника, предложенная в статье, не подходит для корпоративной разработки, хорошо раскрыты в комментариях. Также советую обратить внимание на статью от разработчиков Nexus, спасибо jbaruch за ссылку. Статья интересная, если не найду существующего перевода на Хабре, планирую перевести ее и сделать отдельным постом.
Управление зависимостями в Maven

Добавление зависимостей
Например, в архетипе quickstart автоматически добавляется библиотека JUnit3. Если мы хотим перейти с JUnit3 на JUnit4, то достаточно изменить версию в зависимости:
Чтобы добавить какую-нибудь другую зависимость, например TestNG, надо знать её maven координаты, то есть группу, артефакт и версию:
Переменные в maven
Перед тем как продолжить добавлять зависимости, нужно сделать шаг к переменным в maven. Maven позволяет задавать переменные (а сам задаёт ещё больше), значения которых впоследствии можно использовать где угодно:
И в тег будет подставлено значение «1.2.3».
Те же самые переменные можно и нужно использоват, чтобы задавать версию зависимости отдельно от самой зависимости:
Такое раздельное описание зависимостей имеет два преимущества:
Кстати, подписывать какие зависимости для чего нужны, тоже не лишне.
Области видимости
Вы могли заметить, что описания зависимостей для JUnit и Spring framework отличаются параметром scope, он же — область видимости. Scope позволяет указать maven’у когда и для чего вам нужна эта зависимость. Всего существует шесть областей видимости:
Например, в одном из моих проектов есть такие зависимости:
Maven. Часть 2 – Dependency
В этом уроке я вам покажу основную силу Maven, а именно как создать проект, который можно разрабатывать целой командой и при этом не потребуется каждому члену команды подключать необходимые библиотеки к проекту, давайте начнем.
И так начнем с того, зачем вам нужен Maven? В статье Maven. Часть 1 – Знакомство и настройка мы уже немного разобрали что это и как настроить.
Тут я хочу вам показать как использовать данный инструмент, а покажу вам его использование на примере JUnit тестирования.
Шаг 1. Создание Maven проекта
Запускаем нашу всем любимую Intellij IDEA и нажимаем File->Create New Project
Шаг 2.
Теперь в корне проекта вы должны увидеть файл pom.xml.
И вот что вы должны видеть:
С помощью этого файла и осуществляется настройка сборки вашего проекта. К примеру вам нужно собрать проект в *.jar файл, для этого вам достаточно указать это в pom.xml. Как собрать проект в jar файл вы можете посмотреть тут.
Это файл изначально имеет default (поумолчанию) структуру.
Шаг 3. Используем Dependency
Что же такое dependency и для чего они нужны?
Dependency – это зависимости от библиотек, а если точней, то это и есть библиотека, которую вы бы хотели подключить к проекту.
Рассмотрим на базовом шаблоне:
В выше приведенном примере я продемонстрировал подключение библиотеки JUnit 4.11 к проекту, теперь при сборке проекта эта библиотека упакуется в мой *.jar или *.war архив, а также теперь мы в наших классах можем обращаться к объектам библиотеки JUnit.
– тут мы размещаем список dependency (библиотек), которые используются в проекте;
– библиотека используемая проектом;
– идентификатор группы библиотеки;
Шаг 4. Структура проекта
Стандартная структура каталогов:
Стандартная структура каталогов — одна из реализаций этого принципа.
Поскольку проект её придерживается, отпадает необходимость специфицировать пути к файлам, что сильно упрощает pom.xml.
Следующая структура показывает важнейшие каталоги.
Корневой каталог проекта:
– pom.xml и все дальнейшие подкаталоги;
– src: все исходные файлы;
src/main : исходные файлы собственно для продукта;
src/main/java : Java-исходный текст;
src/main/resources : другие файлы, которые используются при компиляции или исполнении, например Properties-файлы;
src/test : исходные файлы, необходимые для организации автоматического тестирования;
src/test/java : JUnit-тест-задания для автоматического тестирования;
target : все создаваемые в процессе работы Мавена файлы;
target/classes : компилированные Java-классы.
Шаг 5. Жизненный цикл
Жизненный цикл проекта — это список поименованных фаз, определяющий порядок действий при его построении.
Maven использует по умолчанию следующий жизненный цикл:
1) archetype – создание темплейта и обработка ресурсов. На этой фазе разрешаются и, при необходимости, скачиваются из интернета зависимости;
2) compile – компиляция;
3) обработка тестовых ресурсов (например — скачивается из интернета JUnit-пакет);
4) компиляция тестов (тестирующие классы не передаются конечным пользователям);
5) test – тестирование;
6) package – упаковка (обычно речь идёт о создании JAR– или WAR-файла);
7) install – инсталляция проекта в локальном Maven-репозитории (теперь он доступен как модуль для других локальных проектов);
8) deploy – инсталляция в удаленном Maven-репозитории (теперь стабильная версия проекта доступна широкому кругу разработчиков).
Maven имеет также стандартный жизненный цикл для чистки (cleaning) и для генерации его страницы (site). Если бы ‘clean’ было частью обычного жизненного цикла, проект подвергался бы чистке при каждом построении, что нежелательно.
Стандартные жизненные циклы могут быть существенно дополнены Maven-плагинами и Maven-архетипами.
Maven-плагины позволяют вставлять в стандартный цикл новые шаги (например, распределение на сервер приложений) или расширять существующие шаги. Maven-архетипы представляют собой заготовки для различнейших программных пакетов (если они отвечают стандартам Maven-структуры).
Apache Maven — основы
После публикации топика о Maven в комментариях возникли вопросы о том, как начать с ним работать, с чего начать, как составлять файлы pom.xml, откуда брать плагины и т.п. Данный топик будет своего рода getting started или f.a.q.
Терминология
Как в любой системе, в Maven, есть свой набор терминов и понятий.
Вся структура проекта описывается в файле pom.xml (POM – Project Object Model), который должен находиться в корневой папке проекта. Ключевым понятием Maven является артефакт — это, по сути, любая библиотека, хранящаяся в репозитории. Это может быть какая-то зависимость или плагин.
Зависимости — это те библиотеки, которые непосредственно используются в вашем проекте для компиляции кода или его тестирования.
Плагины же используются самим Maven’ом при сборке проекта или для каких-то других целей (деплоймент, создание файлов проекта для Eclipse и др.).
В самом начале работы с Maven, пользователь непременно столкнется с таким понятием как архетип. Архетип — это некая стандартная компоновка файлов и каталогов в проектах различного рода (веб, swing-проекты и прочие). Другими словами, Maven знает, как обычно строятся проекты и в соответствии с архетипом создает структуру каталогов.
Как правило, название артефакта состоит из названия группы, собственного названия и версии. К примеру Spring будет иметь вот такое название в среде Maven: org.springframework.spring:2.5.5. Последний домен означает всегда artifactId, все, что перед ним – groupId – хорошо это запомните!
На жизненном цикле останавливаться не буду, так как он хорошо описан в вышеобозначенной статье. А теперь перейдем к практике.
Установка Maven
Последнюю версию всегда можно скачать на странице загрузки на официальном сайте. Просто распаковываем архив в любую директорию. Далее необходимо создать переменную в Path, в которой необходимо указать путь к Maven. Заходим в Win + Pause – Дополнительно – Переменные среды – в верхнем окошке нажимаем Создать, вводим имя M2_HOME и значение допустим “C:\apache-maven-2.2.1”. Далее там же создаем еще одну переменную M2 со значением %M2_HOME%\bin. Так же убеждаемся, что есть переменная JAVA_HOME с путем к JDK. Ее значение должно быть примерно таким «c:\Program Files\Java\jdk1.6.0_10\». И наконец в том же окошке создаем/модифицируем переменную Path, в нее необходимо просто написать %M2%, чтобы наша папочка с исполняемым файлом Maven была видна из командной строки. Теперь необходимо проверить работоспособность нашей установки. Для этого заходим в командную строку и вводим команду
Должна появиться информация о версиях Maven, jre и операционной системе, что-то вроде:
Maven создаст вам локальный репозиторий в вашей личной папке, например в каталоге C:\Documents and Settings\username\.m2\repository
Все, Maven готов к работе, можно приступать к созданию приложения.
Создание приложения из архетипа
На сайте Maven перечислены наиболее популярные архетипы для приложений, но вы можете легко создать свой или найти более специфичный например здесь.
Итак, допустим нас интересует веб-приложение – находим подходящий архетип, называется он maven-archetype-webapp. В командной строке, в необходимом каталоге выполняем команду Maven:
Теперь мы можем лицезреть довольно наглядную структуру каталогов с говорящими названиями java – здесь будут ваши классы, webapp – здесь размещаются странички веб-приложения, resources – различного рода ресурсы в classpath (файлы конфигурации, например), test – юнит-тесты, соответственно и т.п.
Сборка проекта
Здесь все просто – выполняем команду
в корневом каталоге приложения, там, где находится файл pom.xml. Первая команда скомпилирует ваш проект и поместит его в папку target, а вторая еще и положит его к вам в локальный репозиторий.
Есть полезная функция, наподобие конвеера, то есть можно написать
и Maven сначала очистит папку target проекта, потом соберет его и положит в репозиторий.
Минимальный набор действий для работы Maven мы изучили, теперь переходим к кастомизации и добавлению зависимостей проекта.
Зависимости и репозитории
Как правило, большинство популярных библиотек находятся в центральном репозитории, поэтому их можно прописывать сразу в раздел dependencies вашего pom-файла. Например чтобы подключить Spring Framework необходимо определить следующую зависимость:
Версию хотя и можно не указывать и тогда Maven возьмет последний вариант, но я вам лично советую это делать, потому как у нас неоднократно бывали случаи, что проект просто в один момент переставал собираться или начинал падать в совершенно неожиданных и хорошо оттестированных местах, хотя вроде бы никто ничего не менял.
Специфические вещи обычно не находятся в центральном репозитории и тогда вам придется указать репозиторий производителя вручную. Для примера добавим зависимость JSF-фреймворка ajax-компонентов JBoss RichFaces.
С зависимостями все просто:
А вот репозиторий JBoss теперь необходимо прописать ручками либо в файле settings.xml, который лежит в корне вашего локального репозитория, либо в самом файле pom.xml, в зависимости от того, нужен ли данный репозиторий во всех проектах, либо в каком-то одном конкретном, соответственно:
Как правило на сайтах крупных проектов пишут всю информацию, необходимую для встраивания их библиотеки в проект на основе Maven, но бывают случаи, когда артефакт приходится искать очень и очень долго. Здесь нам очень сильно может помочь MVNrepository.com — он вам всегда подскажет где может находиться искомая библиотечка. Но если уж и там не нашлось, то из собственного опыта могу посоветовать гуглить « pom.xml». Бывает так, что проекты уже давно закрыты и в репозитории не положены потому что разработчики уже не заботятся об их распространении. Тогда остается один единственный способ – добавить файл в репозиторий вручную командой:
Последний параметр чаще всего имеет значение jar.
Плагины
Так как плагины являются такими же артефактами, как и зависимости, то они описываются практически так же. Вместо раздела dependencies – plugins, dependency – plugin, repositories – pluginRepositories, repository – pluginRepository.
Плагинами Maven делает все, даже непосредственно то, для чего он затевался – сборку проекта, только этот плагин необязательно указывать в свойствах проекта, если вы не хотите добавить какие-то фичи.
Посмотрим как настроить плагин для создания проекта для Eclipse с использованием WTP ver. 2.0. В раздел plugins нашего pom.xml прописываем следующий плагин:
Теперь идем опять таки в командную строку и выполняем команду
Ждем пока Maven найдет все библиотеки в репозитории или скачает их и вуаля – теперь наш Maven-проект можно открыть как проект eclipse. При этом библиотеки никуда не копируются как при классическом подходе, а остаются в репозитории и Eclipse делает на них ссылку через свои переменные.
Единого списка всех плагинов естественно не существует, на официальном сайте только есть поддерживаемые плагины непосредственно разработчиками Maven. Однако хотелось бы отметить, что названия плагинов довольно прямолинейны и сделав поиск по ключевым словам «maven tomcat plugin» вы скорее всего обнаружите первой ссылкой плагин для деплоймента проекта в Tomcat.
Собственный репозиторий
К сожалению сам не имею большого опыта настройки репозитория, но могу посоветовать как наиболее простой и распространенный Nexus. За дополнительной информацией следует обратиться на сайт данного проекта.
Однако нельзя оставить без внимания и достойных конкурентов в лице Artifactory и Archiva.


