Можно ли добавить jars в maven 2 build classpath без их установки?
Maven2 сводит меня с ума во время экспериментальной/быстрой и грязной фазы разработки.
У меня есть файл pom.xml
, который определяет зависимости для структуры веб-приложения, которую я хочу использовать, и я могу быстро генерировать стартовые проекты из этого файла. Однако иногда я хочу связать с сторонней библиотекой, у которой еще нет файла pom.xml
, поэтому вместо того, чтобы создавать файл pom.xml
для стороннего lib вручную и устанавливать его, и добавлять зависимость к my pom.xml
, я просто хотел бы сказать Maven: "Помимо моих определенных зависимостей, включите любые банки, которые находятся в /lib
тоже".
Кажется, что это должно быть просто, но если это так, я чего-то не хватает.
Любые указатели на то, как это сделать, очень ценятся. Короче говоря, если есть простой способ указать maven в каталог /lib
и легко создать pom.xml
со всеми вложенными банками, сопоставленными с одной зависимостью, которую я мог бы затем назвать/установить и связать одним махом также будет достаточно.
Ответы
Ответ 1
Проблемы популярных подходов
Большинство ответов, которые вы найдете в Интернете, предложит либо установить зависимость в вашем локальном репозитории, либо указать "системную" область в pom
и распределить зависимость с источником вашего проекта. Но оба этих решения на самом деле ошибочны.
Почему вы не должны применять подход "Установить для локального репо"
Когда вы устанавливаете зависимость в своем локальном репозитории, она остается там. Ваш артефакт распространения будет отлично работать, если он имеет доступ к этому репозиторию. Проблема в большинстве случаев заключается в том, что этот репозиторий будет находиться на вашей локальной машине, поэтому не будет возможности разрешить эту зависимость на любой другой машине. Ясно, что ваш артефакт зависит от конкретной машины - это не способ справиться с ситуациями. В противном случае эта зависимость должна быть локально установлена на каждой машине, работающей с этим проектом, которая не лучше.
Почему вы не должны применять подход "Системная область"
Баны, на которые вы зависите, с подходом "Системная область" не устанавливаются ни в какой репозиторий или не привязаны к вашим целевым пакетам. Поэтому у вашего дистрибутива не будет возможности разрешить эту зависимость при ее использовании. Я считаю, что причиной тому стало то, что использование системной области даже устарело. В любом случае вы не хотите полагаться на устаревшую функцию.
Статическое решение для репозитория в проекте
Поместив это в свой pom
:
<repository>
<id>repo</id>
<releases>
<enabled>true</enabled>
<checksumPolicy>ignore</checksumPolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<url>file://${project.basedir}/repo</url>
</repository>
для каждого артефакта с идентификатором группы формы x.y.z
Maven будет включать следующее местоположение внутри вашего проекта dir в поиске артефактов:
repo/
| - x/
| | - y/
| | | - z/
| | | | - ${artifactId}/
| | | | | - ${version}/
| | | | | | - ${artifactId}-${version}.jar
Чтобы подробнее рассказать об этом, вы можете прочитать это сообщение в блоге.
Использовать Maven для установки в проект repo
Вместо того, чтобы вручную создавать эту структуру, я рекомендую использовать плагин Maven для установки ваших банок в качестве артефактов. Таким образом, для установки артефакта в репозиторий in-project в папке repo
выполните:
mvn install:install-file -DlocalRepositoryPath=repo -DcreateChecksum=true -Dpackaging=jar -Dfile=[your-jar] -DgroupId=[...] -DartifactId=[...] -Dversion=[...]
Если вы выберете этот подход, вы сможете упростить декларацию репозитория в pom
до:
<repository>
<id>repo</id>
<url>file://${project.basedir}/repo</url>
</repository>
Вспомогательный script
Поскольку выполнение команды установки для каждой библиотеки вызывает раздражение и определенно подверженность ошибкам, я создал утилиту script, которая автоматически устанавливает все банки из папки lib
в репозиторий проекта, а также автоматически разрешать все метаданные (groupId, artifactId и т.д.) из имен файлов. script также распечатывает зависимости xml, которые вы можете скопировать-вставить в pom
.
Включить зависимости в целевом пакете
Когда вы создадите репозиторий внутри проекта, вы решите проблему распределения зависимостей проекта с его источником, но с тех пор ваш артефакт проекта будет зависеть от не опубликованных банок, поэтому, когда вы 'установить его в репозиторий, он будет иметь неразрешимые зависимости.
Чтобы обойти эту проблему, я предлагаю включить эти зависимости в ваш целевой пакет. Это можно сделать либо с помощью Плагина сборки, либо с помощью OneJar Plugin. Официальную документацию на OneJar легко понять.
Ответ 2
Только для выброса кода
установить scope == систему и просто создать groupId, artifactId и версию
<dependency>
<groupId>org.swinglabs</groupId>
<artifactId>swingx</artifactId>
<version>0.9.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/swingx-0.9.3.jar</systemPath>
</dependency>
Примечание: системные зависимости не копируются в приведенные jar/war
(см. Как включить системные зависимости в войну, построенные с использованием maven)
Ответ 3
Вы можете создать локальный репозиторий в своем проекте
Например, если в структуре проекта есть libs
-
В папке libs
вы должны создать структуру каталогов, например: /groupId/artifactId/version/artifactId-version.jar
-
В вашем pom.xml вы должны зарегистрировать репозиторий
<repository>
<id>ProjectRepo</id>
<name>ProjectRepo</name>
<url>file://${project.basedir}/libs</url>
</repository>
-
и добавьте зависимость как обычно
<dependency>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<version>version</version>
</dependency>
Вот и все.
Для получения более подробной информации: Как добавить внешние библиотеки в Maven
Ответ 4
Примечание. При использовании области "Система" (как указано на этой странице), Maven нуждается в абсолютных путях.
Если ваши банки находятся под вашим корнем проекта, вам нужно будет префикс ваших значений systemPath с помощью ${basedir}.
Ответ 5
Вам действительно нужно получить фреймворк через репозиторий и определить свои зависимости впереди. Использование области системы - распространенная ошибка, которую люди используют, потому что они "не заботятся об управлении зависимостями". Беда в том, что при этом вы получаете извращенную сборку maven, которая не будет показывать maven в нормальном состоянии. Вам будет лучше следовать подходу, например this.
Ответ 6
Это то, что я сделал, он также работает вокруг проблемы с пакетом, и он работает с извлеченным кодом.
Я создал новую папку в проекте, в моем случае я использовал repo
, но не стесняйтесь использовать src/repo
В моем POM у меня была зависимость, которая не находится в каких-либо общедоступных хранилищах maven
<dependency>
<groupId>com.dovetail</groupId>
<artifactId>zoslog4j</artifactId>
<version>1.0.1</version>
<scope>runtime</scope>
</dependency>
Затем я создал следующие каталоги repo/com/dovetail/zoslog4j/1.0.1
и скопировал JAR файл в эту папку.
Я создал следующий файл POM для представления загруженного файла (этот шаг не является обязательным, но он удаляет ПРЕДУПРЕЖДЕНИЕ) и помогает следующему парню выяснить, откуда я получил файл.
<?xml version="1.0" encoding="UTF-8" ?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dovetail</groupId>
<artifactId>zoslog4j</artifactId>
<packaging>jar</packaging>
<version>1.0.1</version>
<name>z/OS Log4J Appenders</name>
<url>http://dovetail.com/downloads/misc/index.html</url>
<description>Apache Log4j Appender for z/OS Logstreams, files, etc.</description>
</project>
Два дополнительных файла, которые я создаю, это контрольные суммы SHA1 для POM и JAR для удаления отсутствующих предупреждений контрольной суммы.
shasum -b < repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.jar \
> repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.jar.sha1
shasum -b < repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.pom \
> repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.pom.sha1
Наконец, я добавлю следующий фрагмент в свой pom.xml, который позволяет мне ссылаться на локальный репозиторий
<repositories>
<repository>
<id>project</id>
<url>file:///${basedir}/repo</url>
</repository>
</repositories>
Ответ 7
Плагин установки Maven имеет использование командной строки для установки jar в локальный репозиторий, POM не является обязательным, но вам нужно будет указать GroupId, ArtifactId, Version и Packaging (все материалы POM).
Ответ 8
Так мы добавляем или устанавливаем локальную банку
<dependency>
<groupId>org.example</groupId>
<artifactId>iamajar</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/iamajar.jar</systemPath>
</dependency>
i дал некоторые значения по умолчанию groupId и artifactId, потому что они являются обязательными:)
Ответ 9
Использование <scope>system</scope>
является ужасной идеей по причинам, объясняемым другими, установка файла вручную в локальный репозиторий делает сборку невоспроизводимой, а использование <url>file://${project.basedir}/repo</url>
не является хорошей идеей либо потому, что (1) это может быть не правильно сформированный URL file
(например, если проект выгружен в каталоге с необычными символами), (2) результат неприменим, если этот проект POM используется как зависимость от кого-то проекта elses.
Предполагая, что вы не хотите загружать артефакт в общедоступный репозиторий, предложение Симеона о вспомогательном модуле выполняет эту работу. Но теперь есть более простой способ...
Рекомендация
Используйте non-maven-jar-maven-plugin. Именно то, о чем вы просили, без каких-либо недостатков других подходов.
Ответ 10
Я нашел другой способ сделать это, см. здесь сообщение Героку
Подводя итог (извините за некоторые копии и вставки)
- Создайте каталог
repo
в корневой папке:
yourproject
+- pom.xml
+- src
+- repo
- Запустите это, чтобы установить банку в локальный каталог репо
mvn deploy:deploy-file -Durl=file:///path/to/yourproject/repo/ -Dfile=mylib-1.0.jar -DgroupId=com.example -DartifactId=mylib -Dpackaging=jar -Dversion=1.0
<repositories>
<!--other repositories if any-->
<repository>
<id>project.local</id>
<name>project</name>
<url>file:${project.basedir}/repo</url>
</repository>
</repositories>
<dependency>
<groupId>com.example</groupId>
<artifactId>mylib</artifactId>
<version>1.0</version>
</dependency>
Ответ 11
После долгого обсуждения с парнями CloudBees о надлежащей упаковке maven таких JAR-приложений они сделали интересное предложение для решения:
Создание поддельного проекта Maven, который присоединяет ранее существовавший JAR в качестве первичного артефакта, который входит в состав POM install: install-file. Вот пример такого рода POM:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>image-util-id</id>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${basedir}/file-you-want-to-include.jar</file>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<packaging>jar</packaging>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Но для его реализации необходимо изменить существующую структуру проекта. Во-первых, вы должны иметь в виду, что для каждого такого типа JAR должен быть создан другой поддельный проект Maven (модуль). И должен быть создан родительский проект Maven, включающий все подмодули, которые включают: все обертки JAR и существующий основной проект. Структура может быть:
корневой проект (содержащий родительский файл POM включает в себя все подмодули с XML-элементом module) (упаковка POM)
JAR 1 оболочка проекта Maven (упаковка POM)
JAR 2 оболочка проекта Maven (упаковка POM)
основной существующий дочерний проект Maven (WAR, JAR, EAR....)
Когда родительский процесс, запущенный через mvn: install или mvn: упаковка принудительно, и будут выполняться подмодули. Это может быть обеспокоено здесь минусом, поскольку структуру проекта следует изменить, но в конце предлагает нестационарное решение.
Ответ 12
Проблема с systemPath
заключается в том, что банки зависимостей не будут распределены по вашим артефактам как транзитивные зависимости. Попробуйте то, что я разместил здесь: Лучше ли Mavenize создавать файлы проекта jar или помещать их в WEB-INF/lib?
Затем объявляйте зависимости, как обычно.
И, пожалуйста, прочитайте примечание нижнего колонтитула.
Ответ 13
Если вы хотите быстрое и грязное решение, вы можете сделать следующее (хотя я не рекомендую это ни для чего, кроме тестовых проектов, maven будет жаловаться по длине, что это не правильно).
Добавьте запись зависимости для каждого файла jar, который вам нужен, желательно с perl script или что-то подобное и скопируйте/вставьте в ваш файл pom.
#! /usr/bin/perl
foreach my $n (@ARGV) {
[email protected]*/@@;
print "<dependency>
<groupId>local.dummy</groupId>
<artifactId>$n</artifactId>
<version>0.0.1</version>
<scope>system</scope>
<systemPath>\${project.basedir}/lib/$n</systemPath>
</dependency>
";
Ответ 14
Что мне кажется самым простым, просто настройте ваш maven-compiler-plugin, чтобы включить ваши пользовательские банки. В этом примере загружаются любые файлы jar в каталоге lib.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<includes>
<include>lib/*.jar</include>
</includes>
</configuration>
</plugin>
Ответ 15
Быстрое и пакетное решение (на основе ответа Алекса):
libs.bat
@ECHO OFF
FOR %%I IN (*.jar) DO (
echo ^<dependency^>
echo ^<groupId^>local.dummy^</groupId^>
echo ^<artifactId^>%%I^</artifactId^>
echo ^<version^>0.0.1^</version^>
echo ^<scope^>system^</scope^>
echo ^<systemPath^>${project.basedir}/lib/%%I^</systemPath^>
echo ^</dependency^>
)
Выполните его следующим образом: libs.bat > libs.txt
.
Затем откройте libs.txt
и скопируйте его содержимое как зависимости.
В моем случае мне нужно было только библиотеки для компиляции моего кода, и это решение было наилучшим для этой цели.
Ответ 16
Странное решение, которое я нашел:
с помощью Eclipse
- создать простой (не-maven) проект java
- добавить основной класс
- добавить все банки в путь к классам
- export Runnable JAR (это важно, потому что здесь нет другого способа сделать это)
- выберите Извлечь необходимые библиотеки в сгенерированный JAR
- решить проблемы с лицензией.
- tadammm... установить сгенерированную банку в ваш m2repo
- добавьте эту единственную зависимость в другие ваши проекты.
веселит,
Балинт
Ответ 17
Несмотря на то, что это не соответствует вашей проблеме, я брошу это здесь. Мои требования:
- Ящики, которые не могут быть найдены в онлайн-хранилище maven, должны находиться в SVN.
- Если один разработчик добавляет другую библиотеку, другим разработчикам не стоит беспокоиться об установке вручную.
- IDE (NetBeans в моем случае) должна быть в состоянии найти источники и javadocs для предоставления автозаполнения и помощи.
Сначала поговорим о (3): просто наличие банок в папке и каким-то образом их объединение в финальную банку не сработает здесь, так как среда IDE не поймет это. Это означает, что все библиотеки должны быть установлены правильно. Тем не менее, я не хочу, чтобы все устанавливали его с помощью "mvn install-file".
В моем проекте мне нужен метавидит. Здесь мы идем:
- Создайте новый проект maven (назовите его "shared-libs" или что-то в этом роде).
- Загрузите metawidget и извлеките zip в src/main/lib.
- В папке doc/api содержатся javadocs. Создайте почтовый индекс содержимого (doc/api/api.zip).
- Измените pom как это
- Создайте проект, и библиотека будет установлена.
- Добавить библиотеку в зависимости от вашего проекта или (если вы добавили зависимость в проекте shared-libs), добавьте shared-libs в качестве зависимости, чтобы сразу получить все библиотеки.
Каждый раз, когда у вас есть новая библиотека, просто добавьте новое исполнение и расскажите всем, чтобы снова создать проект (вы можете улучшить этот процесс с помощью иерархиев проекта).
Ответ 18
Чтобы установить стороннюю банку, которая не находится в репозитории maven, используйте maven-install-plugin.
Ниже приведены шаги:
- Загрузите файл jar вручную из источника (веб-сайта)
- Создайте папку и поместите в нее свой файл jar
- Запустите команду ниже, чтобы установить стороннюю банку в локальный репозиторий maven.
mvn install: install-file -Dfile = -DgroupId = -DartifactId = -Dversion = -Dpackaging =
Ниже приведен пример, например, я использовал его для simonsite log4j
mvn install: install-file -Dfile =/Пользователи/athanka/ git/MyProject/repo/log4j-rolling-appender.jar -DgroupId = uk.org.simonsite -DartifactId = log4j-roll-appender -Dversion = 20150607-2059 -Dpackaging = jar
-
В pom.xml включена зависимость ниже
<dependency>
<groupId>uk.org.simonsite</groupId>
<artifactId>log4j-rolling-appender</artifactId>
<version>20150607-2059</version>
</dependency>
-
Запустите команду mvn clean install для создания вашей упаковки
Ниже приведена ссылка:
https://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html
Ответ 19
Для тех, кто не нашел здесь хорошего ответа, это то, что мы делаем, чтобы получить банку со всеми необходимыми зависимостями в ней. Этот ответ (fooobar.com/questions/8245/...) упоминает использование плагина Maven Assembly, но на самом деле не дает примера в ответе. И если вы не прочитаете весь путь до конца ответа (довольно длинный), вы можете пропустить его. Добавление ниже к вашему pom.xml приведет к созданию target/${PROJECT_NAME}-${VERSION}-jar-with-dependencies.jar
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<!-- get all project dependencies -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- MainClass in mainfest make a executable jar -->
<archive>
<manifest>
<mainClass>my.package.mainclass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Ответ 20
Это не ответит, как добавить их в ваш POM, и может быть без проблем, но просто добавит ли каталог lib к вашей работе в classpath? Я знаю, что это то, что я делаю, когда мне нужна внешняя банка, которую я не хочу добавлять в мои репозитории Maven.
Надеюсь, что это поможет.
Ответ 21
Что работает в нашем проекте, это то, что написал Архимед Траяно, но у нас в нашем .m2/settings.xml что-то вроде этого:
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://url_to_our_repository</url>
</mirror>
а значение * должно быть изменено на центральное. Поэтому, если его ответ не работает для вас, вы должны проверить свои настройки .xml
Ответ 22
Я упомянул некоторый код python в комментарии к ответу от @alex lehmann, поэтому размещаю его здесь.
def AddJars(jarList):
s1 = ''
for elem in jarList:
s1+= """
<dependency>
<groupId>local.dummy</groupId>
<artifactId>%s</artifactId>
<version>0.0.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/manual_jars/%s</systemPath>
</dependency>\n"""%(elem, elem)
return s1
Ответ 23
Вы можете добавить jar, выполнив:
Для gradle просто поместите следующий код в build.gradle
:
dependencies {
...
compile fileTree(dir: 'lib', includes: ['suitetalk-*0.jar'])
...
}
а для мавена просто следуйте шагам:
Для Intellij: File-> проект structure-> modules-> зависимость tab-> нажмите + sign-> jar и dependency-> выберите банки, которые вы хотите import-> ok-> применить (если они видны) ) → оК
Помните, что если у вас есть какой-либо java.lang.NoClassDefFoundError: Could not initialize class
исключение java.lang.NoClassDefFoundError: Could not initialize class
во время выполнения, это означает, что зависимости в jar не установлены, для этого вам нужно добавить все зависимости в родительский проект.
Ответ 24
Мне просто нужен быстрый и грязный обходной путь... Я не мог запустить script из Nikita Volkov: синтаксическая ошибка + для этого требуется строгий формат для названий баннеров.
Я сделал этот Perl script, который работает с любым форматом для имен файлов jar и генерирует зависимости в xml, чтобы его можно было скопировать в pom.
Если вы хотите использовать его, убедитесь, что вы понимаете, что делает script, вам может потребоваться изменить папку lib
и значение для groupId
или artifactId
...
#!/usr/bin/perl
use strict;
use warnings;
open(my $fh, '>', 'dependencies.xml') or die "Could not open file 'dependencies.xml' $!";
foreach my $file (glob("lib/*.jar")) {
print "$file\n";
my $groupId = "my.mess";
my $artifactId = "";
my $version = "0.1-SNAPSHOT";
if ($file =~ /\/([^\/]*?)(-([0-9v\._]*))?\.jar$/) {
$artifactId = $1;
if (defined($3)) {
$version = $3;
}
`mvn install:install-file -Dfile=$file -DgroupId=$groupId -DartifactId=$artifactId -Dversion=$version -Dpackaging=jar`;
print $fh "<dependency>\n\t<groupId>$groupId</groupId>\n\t<artifactId>$artifactId</artifactId>\n\t<version>$version</version>\n</dependency>\n";
print " => $groupId:$artifactId:$version\n";
} else {
print "##### BEUH...\n";
}
}
close $fh;