В статье я расскажу, как подключить библиотеку, которой в maven по умолчанию нет, и как подключить другую библиотеку, исходники которой давным-давно потеряны.
Также я опишу, как сделать maven проект, который генерирует артефакт, по совместительству являющийся библиотекой, и как подключить эту библиотеку к другому своему же maven проекту.
Эта статья для тех, кто только начинает осваивать java.
В моей предыдущей статье было сказано, что maven сам скачает все указанные в pom.xml зависимости. А вот что будет, если он какую-нибудь зависимость не найдёт? В таком случае maven скажет, что зависимость не обнаружена и прервёт процесс сборки с ошибкой. Что делать в этом случае?
Этот вопрос, на самом деле, распадается на несколько вопросов, каждый из которых надо решать индивидуально. Выбор решения же определяется тем, где эта зависимость есть.
Зависимость может быть в интернете в каком-то месте, о существовании которого maven не знает. Ещё она может быть в виде jar файла у вас на руках и, наконец, в виде исходного кода, оформленного как maven проект.
Об этих трёх случаях мы и поговорим.
Но сначала надо коротко прояснить один вопрос.
Откуда maven качает библиотеки
На просторах интернета есть сервер, на котором выложены java библиотеки. Этот сервер называется репозиторием, а по-русски — хранилищем. Это не какой-то абстрактный, а вполне конкретный ресурс, адрес которого зашит в дефолтные настройки maven. Поэтому он называется репозиторием по умолчанию. Именно там maven будет искать зависимости из pom.xml.
Как быть, если библиотеки нет в удалённом хранилище по умолчанию, но она есть в другом удалённом хранилище
Первая и, возможно, самая частая проблема возникает, если библиотеки в этом умолчальном репозитории нет или в случае, если этот репозиторий с машины, на которой осуществляется сборка, недоступен, например, по соображениям безопасности.
Причины проблемы немного разные, но решение одинаковое — нужно указать репозиторий, в котором зависимости есть. Это либо какой-то другой адрес в Интернете, либо адрес репозитория, поднятого админами в локальной сети.
Как указать maven проекту, где искать дополнительный репозиторий
Для того, чтобы указать maven, что зависимости надо искать не только в умолчальном репозитории, существует штатный механизм. Вот так можно прописать ещё один адрес для поиска.
<repositories>
<repository>
<id>id репозитория</id>
<url>адрес репозитория</url>
</repository>
</repositories>
Далее мы подключили репозиторий проекта Spring, в котором можно найти последние версии этого семейства бибилиотек. Вот как это выглядит внутри pom.xml
<repository>
<id>com.springsource.repository.bundles.release </id>
<url>http://repository.springsource.com/maven/bundles/release </url>
</repository>
Теперь maven, когда не найдёт зависимости в репозитории по умолчанию, или обнаружит, что оный недоступен — не запаникует, а поищет библиотеку в ещё одном репозитории и, если всё идёт по плану, найдёт её там. Тут следует уточнить, что если ваша программа может быть использована в качестве зависимости, например, если сама является библиотекой, то класть тег репозиторий в pom.xml — не лучшая идея. Объяснение того, почему это так, выходит за рамки статьи, но с ним можно ознакомиться тут.
Но бывает так, что библиотеки в репозиториях нет. Например, если это драйвера для MSSQL, или если это проприетарная библиотека, которую вы недавно приобрели за большие деньги.
Как подключить библиотеку, которой в репозиториях нет
Подключить такую библиотеку можно несколькими способами. Например, если у вас есть свой репозиторий в локальной сети, то можно (а иногда даже нужно), положить библиотеку туда, и тем самым свести задачу к предыдущей.
Но, если это возможно, такую библиотеку лучше положить в проект и хранить прямо в системе контроля версий. Тогда библиотека будет доступна программе всегда и на любой машине, а шаг по копированию этой библиотеки в репозиторий можно не включать в мануал.
Для обработки таких кейсов у maven тоже есть штатный механизм. Только что мы выяснили, как указать maven удалённый репозиторий, отличный от умолчального. Так вот, не обязательно использовать удалённое хранилище. Можно сделать репозиторий в локальной файловой системе, положить туда библиотеку и проинструктировать maven искать зависимости ещё и там.
Как создать свой локальный репозиторий
Для этого, как сказано выше, у maven есть штатное средство.
Допустим у нас есть библиотека, которая находится в jar файле под названием hello-world-library-1.0-SNAPSHOT.jar. О библиотеке нам известно, что в ней есть один класс HelloWorld, который включает один статический метод say, печатающий в консоли, как несложно догадаться, Hello World.
Мы хотим в директории проекта создать директорию lib, в которой будет находиться наш дополнительный репозиторий, и поместить туда библиотеку. Для этого достаточно в директории проекта выполнить следующую команду.
mvn deploy:deploy-file -Durl=file:./lib -Dfile=hello-world-library-1.0-SNAPSHOT.jar -DgroupId=com.local -DartifactId=hello-world-library-local -Dpackaging=jar -Dversion=1.0-SNAPSHOT
Если вы используете операционную систему Windows, нужно заменить \ на ^, то есть написать
mvn ^
deploy:deploy-file ^
-Durl=file:./lib ^
-Dfile=hello-world-library-1.0-SNAPSHOT.jar ^
-DgroupId=com.local ^
-DartifactId=hello-world-library-local ^
-Dpackaging=jar ^
-Dversion=1.0-SNAPSHOT
Или можно просто убрать \ и написать команду в одну строчку.
mvn deploy:deploy-file -Durl=file:./lib -Dfile=hello-world-library-1.0-SNAPSHOT.jar -DgroupId=com.local -DartifactId=hello-world-library-local -Dpackaging=jar -Dversion=1.0-SNAPSHOT
Обратите внимание, как и для любого другого артефакта, для библиотеки нам нужно придумать groupId, artifactId и version. Мы потом укажем их в pom.xml, когда будем подключать зависимость.
Внутри директории, которую создаст команда, находится полноценный репозиторий, для использования которого достаточно указать maven, где он находится. Все сведения о том, какие библиотеки можно там найти, содержатся непосредственно в структуре директорий свежесозданного репозитория. Для последующего использования репозитория, например, на других машинах, команду deploy-file выполнять не надо.
Дать проекту знать, что репозиторий существует, и показать, где он находится, можно уже описанным способом, правда, с поправкой на то, что репозиторий локальный.
<repositories>
<repository>
<id>localrep</id>
<name>local repository</name>
<url>file:${project.basedir}/lib</url>
</repository>
</repositories>
Обратите внимание на пятую строку
<url>file:${project.basedir}/lib</url>
Тут сказано, что искать репозиторий надо в директории проекта, на которую указывает встроенная переменная maven project.basedir.
Класс, использующий библиотеку, будет предельно прост, но для порядка приведём его код.
package com;
import static com.HelloWorld.say;
public class Application {
public static void main(String[] argv) {
say();
}
}
Осталось добавить в pom.xml зависимость и можно собирать проект.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>library-user-with-local-repository</artifactId>
<version>1.0-SNAPSHOT</version>
<repositories>
<repository>
<id>localrep</id>
<name>local repository</name>
<url>file:${project.basedir}/lib</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.local</groupId>
<artifactId>hello-world-library-local</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
Проверим:
mvn clean compile exec:java -Dexec.mainClass="com.Application"
Работает!
Директорию lib надо закомитить и библиотека будет доступна проекту вообще всегда.
Однако следует помнить об одном правиле.
Нужно обязательно обновлять номер версии библиотеки в локальном репозитории при каждом изменении jar файла
Maven воспринимает репозитории как внешние, поэтому, если не изменить номер версии, то maven будет использовать не версию библиотеки из директории lib, а ту, что он закешировал на локальной машине. В данном конкретном случае это не должно сыграть роли из-за суффикса SNAPSHOT, но об этом нужно знать.
Есть ещё один распространённый сценарий. У вас есть своя библиотека, которую вы сами собираете с помощью maven и потом подключаете к другому maven проекту.
Как сделать свою java библиотеку
Для того, чтобы сделать библиотеку, достаточно написать класс с модификатором public. И потом можно будет использовать этот класс в коде, к которому подключена библиотека.
Вот такой, например, класс.
package com;
public class HelloWorld {
public static void say() {
System.out.println("Hello world");
}
}
Теперь нужно сделать maven проект, который будет собирать библиотеку, содержащую этот класс.
Как мы помним, с точки зрения maven, библиотека — это просто артефакт, поэтому помник будет выглядеть тривиально.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>hello-world-library</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
Итак, у нас есть класс со статическим методом, у нас есть описание артефакта для maven. Осталось только собрать этот код, чтобы получилась библиотека, то есть jar файл.
Просто напишем в консоли:
mvn package
После этого в директории target появится файл с названием \<artifactId>-\<version>.jar, в нашем конткретном случае — hello-world-library-1.0-SNAPSHOT.jar, который и есть ваша библиотека.
Как подключить свежесозданную библиотеку к своему maven проекту
Для того, чтобы библиотеку потом можно было подключать к другому проекту, нужно вместо package написать install.
mvn install
Это нужно будет делать после каждого изменения в коде библиотеки, и на каждом компьютере, на котором мы захотим эту библиотеку использовать.
Теперь можно сделать новый проект, который будет использовать библиотеку.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com</groupId>
<artifactId>hello-world-library</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
Внутри проекта будет один класс, который использует статический метод из библиотеки, чтобы сказать Hello world. Мы этот класс уже видели.
package com;
import static com.HelloWorld.say;
public class Application {
public static void main(String[] argv) {
say();
}
}
Проверим ещё раз:
mvn compile exec:java -Dexec.mainClass="com.Application"
Работает не хуже предыдущего варианта!
Что если ваша библиотека использует другую библиотеку?
Вопрос, казалось бы, глупый, но на всякий случай проведём эксперимент.
Сделаем библиотеку с непустыми зависимостями.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>hello-world-library</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
</dependencies>
</project>
и напишем для неё код
package com;
import static org.apache.commons.lang3.ArrayUtils.*;
public class HelloWorld {
public static void say() {
String[] phrase = {"Hello"};
phrase = add(phrase, " ");
phrase = add(phrase, "world");
for (String word : phrase) {
System.out.print(word);
}
System.out.println();
}
}
Теперь соберём её
mvn clean install
Перейдём в директорию с нашим проектом, который эту библиотеку использует и попробуем его собрать и запустить.
mvn clean compile exec:java -Dexec.mainClass="com.Application"
И работает!
Как это работает
Строго говоря знать, как процесс устроен внутри, не обязательно, но всё равно очень полезно.
Команда mvn install соберёт библиотеку, а потом положит её в локальный репозиторий по умолчанию. То есть в то же самое место, где лежат все библиотеки, которые вы когда-либо подключали к maven проектам, за исключением, разумеется, тех, которые находятся в локальных репозиториях, сделанных лично вами.
Потом, при сборке проекта, использующего эту библиотеку, maven поищет её в локальном хранилище, найдёт и подключит.
Итого
- Maven ищет библиотеки в удалённом репозитории по умолчанию.
- Чтобы подключить библиотеку, которой нет в репозитории по умолчанию, можно указать дополнительные удалённые репозитории, тогда maven будет искать библиотеки ещё и в них.
- Если библиотеки нет ни в одном удалённом репозитории, то можно с помощью штатного механизма maven создать локальный репозиторий и добавить его в pom.xml.
- При обновлении репозитория, который находится в исходниках проекта, нужно всегда менять версию библиотеки, иначе могут быть непонятные проблемы.
- Если у вас есть maven проект, то из него можно сделать библиотеку командой mvn package.
- Командой mvn install можно поместить библиотеку в локальный репозиторий по умолчанию.
- Чтобы использовать библиотеку в другом проекте, достаточно указать её в качестве зависимости в pom.xml.
UPD: В комментариях sshikov, igor_suhorukov, jbaruch и другие высказали мнение, что библиотеки нельзя хранить вместе с исходниками, потому что для этого есть другие, предназначенные специально для этого инструменты, такие как Nexus и Artifactory.
Тут я совершенно согласен. Когда речь идёт о крупных проектах и корпоративной разработке, быть по-другому просто не может. Но, с моей точки зрения, есть случаи, когда удобнее сделать иначе. Я имею в виду маленькие проекты, созданные в процессе обучения, потому что именно с такими вещами обычно имеют дело новички, и случаи, когда доступа к инфраструктуре нет, а добавить библиотеку в сборку нужно в течение 10 минут. Нужно было с самого начала уточнить, что речь в статье именно о таких кейсах.
Да, хранить библиотеки в системе контроля версий — хак. Но, как и все хаки, это такая штука, которой в некоторых случаях можно пользоваться и о возможности осуществления которой неплохо бы знать.
Причины, по которым техника, предложенная в статье, не подходит для корпоративной разработки, хорошо раскрыты в комментариях. Также советую обратить внимание на статью от разработчиков Nexus, спасибо jbaruch за ссылку. Статья интересная, если не найду существующего перевода на Хабре, планирую перевести ее и сделать отдельным постом.
Комментарии (55)
vaniaPooh
02.03.2017 13:44mvn deploy:deploy-file
А потом вы ошибаетесь в -Dpackaging=pom и записываете вместо pom — jar. Поздравляю — у вас битый локальный репозиторий и теперь резолв артефакта будет идти с ошибкой.poxvuibr
02.03.2017 14:18-3Это же попадёт в систему контроля версий. Можно будет по коммиту найти виноватых, наказать невиновных и наградить непричастных :)
Throwable
02.03.2017 13:59Есть одна проблема с локальным репозиторием — для мультимодульного проекта придется корректировать путь к нему в каждом pom.xml, так как project.badedir будет у каждого модуля свой.
poxvuibr
02.03.2017 14:09-1Есть одна проблема с локальным репозиторием — для мультимодульного проекта придется корректировать путь к нему в каждом pom.xml, так как project.badedir будет у каждого модуля свой.
Есть, да. Многомодульному проекту в maven вообще хочется посвятить отдельную публикацию — очень уж актуальная и важная тема.
sbnur
02.03.2017 15:01К слову, maven уже 15 лет и означает собиратель знаний
Это к тому, что уже давно все собрано в смысле знаний о самом maven и его использованииvba
02.03.2017 15:40+1Да 15 лет и такое впечатление что он нисколько не изменился за эти 15 лет, да и просто не может меняться.
poxvuibr
02.03.2017 15:44+1Ньютоновской физике даже больше 15, а учебники всё пишут и пишут :). Я попытался написать статью именно такой, какой хотел видеть её, когда про maven ещё ничего не знал. Написал с надеждой, что найдутся люди, которым будет удобно получить знания именно в такой форме.
AstarothAst
02.03.2017 16:48+2Найдутся! В смысле — уже нашлись :) Пишите, пожалуйста, еще. Мавен — это инструмент, и им, как и любым инструментом, хочется «просто пользоваться» не затрачивая массу усилий на то что б понять, как же эту хреновину уже заставить работать и перейти к тем проблемам, из-за которых все тут собрались — собственно к программированию.
jehy
02.03.2017 18:46-3А гораздо проще сделать это так:
maven { url 'https://jitpack.io' }
dependencies {
compile 'com.github.jehy:Tor-Onion-Proxy-Library:0.0.5'
}
И вот у вас прямо из гитхаба идёт импорт.poxvuibr
02.03.2017 19:29+1Во-первых это не совсем maven :). А во-вторых импорты с гитхаба штука опасная, если он конечно не твой собственный.
jehy
02.03.2017 19:36-1Во-первых, не вижу разницы для разработчика.
Во-вторых, никто не отменял форки.poxvuibr
03.03.2017 09:12+1Ну, тема статьи всё-таки maven. Поэтому на всякий случай перепишу ваше замечание так, чтобы оно лучше соответствовало контексту статьи.
<repository> <id>jitpack.io</id> <url>https://jitpack.io</url> </repository> <dependency> <groupId>com.github.jehy</groupId> <artifactId>Tor-Onion-Proxy-Library</artifactId> <version>0.0.5</version> </dependency>
Действительно неплохой способ. Собирать библиотеки только нужно, но для многих это скорее плюс, чем минус. Жаль только завязан на проприетарную технологию с закрытым кодом. А так — вполне себе.
jbaruch
03.03.2017 19:53прописывать repository в поме — огромная ошибка. Никогда так не делайте, и никого не учите так делать. Вот вам блог пост от создателей мавена:
http://blog.sonatype.com/2009/02/why-putting-repositories-in-your-poms-is-a-bad-idea/poxvuibr
06.03.2017 13:11repository в pom.xml это действительно не всегда хорошо. Однако, в приведённой вами статье написано, что в случае, если продуктом является программа, которую не собираются использовать в качестве зависимости, то указание репозитория в помнике вполне безопасно. И, если вы хотите упростить сборку проекта для других разработчиков эта идея вполне заслуживает рассмотрения. Именно о таких кейсах я говорил. Спасибо за замечание, добавил уточнение в статье.
jbaruch
06.03.2017 13:45В приведенной мной статье, персонажи, которые придумали этот ад изначально, пытаются оправдаться в стиле «да, это конечно ужас, но не ужас-ужас». Repository в pom это bad practice, и точка. Settings.xml всё равно надо будет генерить для каждого разработчика (потому что там их личные credentials), поэтому нет никаких проблем держать там репозитории тоже.
igor_suhorukov
02.03.2017 23:44+3Но, если это возможно, такую библиотеку лучше положить в проект и хранить прямо в системе контроля версий. Тогда библиотека будет доступна программе всегда и на любой машине, а шаг по копированию этой библиотеки в репозиторий можно не включать в мануал.
А вот так делать не надо!!! Есть грань между SCM и binary repository manager которую не следует путать. Свой собственный корпоративный репозитарий — правильное решение. Хранение библиотек в SCM — грязный хак!poxvuibr
03.03.2017 08:17А вот так делать не надо!!! Есть грань между SCM и binary repository manager которую не следует путать.
Вопрос в том, где эта грань. Тут как с картинками и всем таким. Если у вас их пара гигабайт, то нужно хранить отдельно. Хотя всякое бывает :). А, если пара иконок, то обычно хранят прямо в системе контроля версий. С библиотеками похожая ситуация. Если есть один проприетарный драйвер, или небольшой джарник из эпохи мамонтов с утерянными исходниками — то можно и прямо в исходники положить. А если там целая система с зависимостями, то лучше как-то по другому делать.
Свой собственный корпоративный репозитарий — правильное решение.
Особенно, если у вас есть своя собственная корпорация :). А если у вас свой проектик с парой джарников, то корпоративный репозиторий возможно и оверкилл.
Хранение библиотек в SCM — грязный хак!
Может и так, но в гите оптимизации для хранения бинарников появились не от того, что разработчикам просто нечего было делать.
sshikov
03.03.2017 09:28+1Свой репозиторий оверкилл только если результат проекта вам почти совсем не важен. А если важен — то репозиторий все равно понадобится. В идеале — положить в central. И потом — это в конечном счете быстрее, иметь свой кеш внутри команды.
А про хранение внутри SCM — я бы сказал так: хранить можно, но желательно даже в этом случае разделить репозитории. Пусть у вас будет git repo — но отдельный и только для артефактов. У них другой жизненный цикл, чем у ваших исходников, вы не будете делать такие же бранчи, релизить, и прочее и прочеее. А значит — разделить.
igor_suhorukov
03.03.2017 10:06+1А если у вас свой проектик с парой джарников, то корпоративный репозиторий возможно и оверкилл.
Для проектов с открытым исходным кодом можно использовать центральный репозитарий. Тогда ваши артефакты могут указывать в зависимостях без подкладываний jar в SCM или deploy в корпоративный репозитарий. Есть nexus opensource edition и установка простая — скачал и запустил. Если же проект не open source и вам лень ставить свой менеджер репозитариев и делать бэкапы, то можете раскошелиться на подписку bintray и использовать как сервис для не общедоступного репозитария.
Может и так, но в гите оптимизации для хранения бинарников появились не от того, что разработчикам просто нечего было делать.
По мне так ответ проще — для хранения jpg/png для веб приложений, которых огромное число в github.poxvuibr
03.03.2017 10:20Если же проект не open source и вам лень ставить свой менеджер репозитариев и делать бэкапы, то можете раскошелиться на подписку bintray и использовать как сервис для не общедоступного репозитария.
Тут уже, думаю, вопрос личных предпочтений. Если вы считаете, что ради того, чтобы положить пару джарок в проект имеет смысл поставить Нексус или купить подписку на bintray, то, конечно надо так и делать. Я бы задумался об этом после того, как понял, что джарки придётся регулярно обновлять.
igor_suhorukov
03.03.2017 19:12Странно что jbaruch промолчал про bintray и эту ситуацию со складированием библиотек в SCM…
sshikov
03.03.2017 19:54А что не так с bintray? Это же и есть репозиторий, в общем-то.
Что же до SCM — то есть помнится возможность деплоить туда артефакты при помощи штатного механизма — т.е. mvn deploy. При этом SCM у вас играет роль хранилища, но работаете вы с ним как с репозиторием.
Я бы сказал, что такой подход — он ограниченно годится, но в тоже время совершенно ясно, что он даже не столько от бедности, сколько от лени. Ну опять же — потому что трудозатраты на установку своего репозитория они настолько маленькие, что это даже не смешно.
У меня вот в проекте (предыдущем на сегодня) был (и есть) nexus. Тому нексусу — наверное лет 6 или 10 уже. Никого из тех, кто его развертывал, уже давно в компании нет. Рядом, если что, такой же дремучий jenkins. Никто их не поддерживает — разве что время от времени чистят диск от ненужных сборок jenkins. И работают с этим добром человек 20. Вот такие они — трудозатраты, по стоимости машинки для запуска (виртуалка на два ядра и 8Гб) и диска для размещения всего добра, гигабайт на 100.jbaruch
03.03.2017 21:43С бинтреем всё так, но он просто не для разработки, а для дистрибуции. Для разработки больше Артифактори подходит. Мы в Разборе Полётов всё таки когда нибудь доберемся до разницы между ними (но не в следущем выпуске точно).
sshikov
03.03.2017 22:12+1Тут понимаете еще какая штука… Сначала пара jar, потом десять. А потом будет как в одном моем старом проекте — огромная папка lib, одна на 50 проектов, и порядка 50-же разработчиков.
И валяется там на 99% вполне себе open source, типа commons collections, и огромная проблема со всем этим состоит в том, что никто уже не знает, какому проекту на самом деле какие завимости нужны, кто от кого зависит, какие у них версии, и прочая и прочая.
Там правда к этому еще прилагался ant, но разница в общем не очень велика, потому что главная проблема не в том, чем собирать, а в том, что где-то в lib лежит нечто, о чем мы не знаем, как его точно зовут, и какой оно версии. И если завтра кто-то заменит в SCM один jar на другой, похожий — мы долго будем думать, почему оно вдруг сломалось.
jbaruch
03.03.2017 19:40+1Bintray такой же бесплатный для opensource, а jcenter такой же центральный как и central, и Artifactory такой же бесплатный и опенсорцный как Нексус (только у нас генератор settings.xml и/или maven plugin еще есть).
https://www.youtube.com/watch?v=MGXrPz9wwOY
https://www.jfrog.com/confluence/display/RTF/Maven+Artifactory+Plugingrossws
03.03.2017 21:35Всё-таки central — репозиторий по умолчанию для maven'а, а jcenter надо явно прописывать в
settings.xml
или добавлять в группу в nexus/artifactory. С остальным сложно не согласиться ,)jbaruch
03.03.2017 21:42Да, но с генераторами сеттингов и в Бинтрее и в Артифактори это достаточно просто.
jbaruch
03.03.2017 19:21+4Что же вы делаете-то?! Tutorial в корпоративном блоге предлагает "Директорию lib надо закомитить и библиотека будет доступна проекту вообще всегда"? Я думаю следущая статья должна быть о том, как сорцы лучше пересылать по email-у.
grossws
03.03.2017 21:31+3К сожалению, эта тенденция в большинстве корпоративных блогов на хабре. Есть исключения (в особенности среди больших корпоратов типа mailru/yandex/ibm), но большинство тупо получает деньги за количество знаков, а не качество, вот и прёт индусятина в новом обличье.
jbaruch
03.03.2017 21:41Вот индусам сейчас обидно было.
grossws
03.03.2017 21:44+1Не все индусы одинаково полезны. Я знаю некоторое количество тех, кто реально неплохой код пишет и поддерживает. Но иногда с ужасом вспоминаю исходники какого-нибудь Atlassian Crowd'а.
jbaruch
03.03.2017 21:52Как и не все русские, и не все американцы, я бы сказал. Особенно в свете обсуждения качества статей на Хабре.
grossws
03.03.2017 22:06+1Стереотип не на пустом месте появился, и отсылка была именно к нему, а не к национальности.
Проблема-то та же самая, многим копирайтерам платят за объём и частоту публикаций, а не за качество, так что результат немного предсказуем.
grossws
03.03.2017 21:42@jbaruch, раз уж вы здесь, поведайте как у artifactory (open-source варианта) обстоят дела по следующим направлениям:
- внешняя authn/authz через http-заголовок (типа
REMOTE_USER
) или openid connect; - как с возможностью автоматического деплоя в него из jenkins (при использовании jenkinsfile/pipeline plugin);
- как с возможностью использования webhook'ов/rest api для уведомлений о деплое артифакта?
В принципе, artifactory мне на первый взгляд приятней, чем nexus (а в третьей версии он таки местами ужасен), но когда смотрел в прошлый раз, отсутствие некоторых фич было блокером для сборки CI/CD pipeline'а на open-source варианте.
jbaruch
03.03.2017 21:46+1- В бесплатном есть только LDAP
- Это конечно всё есть, и через Artifactory Jenkins Plugin, и через Artifactory Maven Plugin (оба open source) и просто через mvn deploy
- Это через user plugin, который в Pro.
grossws
03.03.2017 22:03Понятно, спасибо. Т. е. в теории вполне реально, если всё делать со стороны jenkins'а. Надо пробовать.
В планах sso/oidc отдать в opensource нет? То у меня есть впечатление, что раньше ldap был только в pro. И аналогичный вопрос про docker-репозитории.
sshikov
03.03.2017 22:27Пардон, мне кажется, или вы хотите странного?
1. Вы когда деплоите, вы скорее всего используете http, и один из стандартных механизмов аутентификации юзера. Basic, NTLM, SSL. Чтобы использовать тут внешнюю, нужно допилить maven deploy plugin, а точнее видимо вагон. Внешняя тут зачем, чтобы использовать ее в этом месте вместо LDAP? Тогда это Artifactory Security Realm (ровно также, как у nexus впрочем). Это не очень сложно, я пробовал.
2. Проще всего mvn deploy, разумеется. Остальное дополнительные плюшки.
3. В nexus для этого есть RSS и расылка нотификаций почтой. Как вы хотите получать уведомления, если это асинхронный процесс? Чей это должен быть REST? Jenkins, чтобы он собрал другой зависимый артефакт?grossws
03.03.2017 22:50Не то чтобы очень странного ,)
- Я не против использования http authn для деплоя (из jenkins'а или из maven/gradle/sbt — не важно), но для работы с самим artifactory/nexus хочется иметь поменьше геморроя, в частности SSO. OIDC в этом плане является стандартом наравне с более сложным и неприятным SAML, который мне сильно избыточен. И сервер авторизации, поддерживающий OIDC (Keycloak в моём случае) может поддерживать, например, 2fa/client tls auth и подобные радости.
- про
mvn deploy
всё более-менее понятно. Он мне местами не очень нравится (в частности, необходимостью дублироватьscm
и иметьdistributionManagement
в parent'е). Причем, иногда хочется из jenkins'а подтвердить promotion в stage окружение, а далее в release. С jenkins pipeline это вполне реализуемо. Но пока у меня нет устоявшегося представление как это всё будет выглядеть, так что я присматриваюсь к разным вариантам. - В свой сервис обычным http callback'ом (т. е. то, что обычно и понимается под webhook'ом), а он уже может выполнять задачи по уведомлению, используя какой-нибудь slack и т. п. Вполне возможно, что всё может делаться из jenkins'а и придумал себе проблему на пустом месте.
jbaruch
04.03.2017 05:10- Он хочет вот это: https://www.jfrog.com/confluence/display/RTF/Single+Sign-on
- внешняя authn/authz через http-заголовок (типа
sshikov
Ну вот зачем вы учите начинающих плохому? )))
Есть менеджеры репозиториев, например nexus и artifactory. У них есть полноценные бесплатные версии, которые (конкретно могу утверждать про nexus, но не думаю что с другими все сильно отличается) устанавливаются и запускаются максимум за полчаса. Есть например готовые docker images, откуда можно запустить вообще без усилий, если у вас есть docker.
И дальше свой nexus надо прописать раз и навсегда в settings.xml, и с ним работать. Если вы не кустарь одиночка с мотором (с), это будет одно из правильных решений. А если вы работаете в команде — то пожалуй и единственно правильное.
Установить и запустить. И дальше все проблемы будут решаться через UI — задеплоить артефакт, которого нет в репозиториях, подключить еще один репозиторий помимо central, и прочее, и прочее.
poxvuibr
Я тут совершенно согласен часто нужно класть библиотеки именно туда. В статье об этом есть ремарка :)
А вот тут я считаю, что настройки надо по возможности воткнуть в pom.xml и завернуть в maven профиль, чтобы не было необходимости что-то настраивать в settings.xml
А если вы в команде — тем более класть в профиль, чтобы не заниматься правкой settings.xml на регулярной основе
Это, повторюсь, хороший вариант. В статье я хотел сделать фокус именно на работе с maven. Этот вариант работы, на мой взгляд, описан в пункте про подключение удалённого репозитория.
sshikov
Да, с поправками насчет settings и пр. — согласен.
Собственно, я имел в виду, что ваши варианты — они конечно да, самые базовые, но в реальности все-таки намного проще настроить репозиторий. В случае компании, которая живет в интранете — это просто must have, без вариантов вообще. И на это стоило бы напирать сильнее.
Throwable
Я не совсем согласен с такой точкой зрения. Иметь свой корпоративный репозиторий в команде это, конечно же, хорошо и правильно. Но я всегда следую принципу, что проект должен уметь собираться всегда и везде, без лишних геморроев. Локальный репозиторий проекта — разумное решение, когда тебе нужен всего лишь какой-нибудь пропиетарный драйвер. Это делает сборку проекта автономной и независимой от окружения. Maven Wrapper при этом еще отлично помогает.
sshikov
Ну да. Наверное все-таки стоит разделить проекты на open source (которым в первую очередь нужно собираться везде), и скажем так, корпоративные.
Но с другой стороны, для maven же есть средства, которые умеют копировать репозитории целиком. Так что если у вас зависимости лежат скажем на github в виде локального репозитория, перетащить их в nexus будет совсем просто.
poxvuibr
Именно это я и имел в виду. А Maven Wrapper — вещь! Я когда gradlew увидел — долго горевал, что для maven такого нет. Пока через час не выяснил, что вполне себе есть!
jbaruch
Спасибо, дорогой за луч света в этом плотном слое говна. Я тут обфейспалмился до крови, читая этот ад (я про статью, конечно). У Artifactory тоже есть бесплатный оpensource, конечно. У нас есть генератор settings.xml, который вообще делает всё за тебя: https://www.youtube.com/watch?v=MGXrPz9wwOY
Кроме того, у нас есть еще и Maven plugin, который добавляет metadata к задеплоенным артифактам.