Могу ли я добавить файлы jar в maven 2 buildpath без их установки?

Maven2 сводит меня с ума во время фазы эксперимента / быстрого и грязного макета разработки.

у меня есть pom.xml файл, который определяет зависимости для структуры веб-приложения, которую я хочу использовать, и я могу быстро сгенерировать начальные проекты из этого файла. Тем не менее, иногда я хочу сделать ссылку на стороннюю библиотеку, которая еще не имеет pom.xml файл, а не создавать pom.xml вручную запустите сторонний lib и установите его, а также добавьте зависимость к моему pom.xmlЯ просто хотел бы сказать Maven: "В дополнение к моим определенным зависимостям, включите любые jar-файлы, которые находятся в /lib тоже."

Кажется, это должно быть просто, но если это так, я что-то упускаю.

Любые указатели о том, как это сделать, с благодарностью. Если не считать этого, если есть простой способ указать Maven на /lib каталог и легко создать pom.xml со всеми вложенными jar-файлами, сопоставленными с одной зависимостью, которую я мог бы затем назвать / установить и ссылаться на нее одним махом;

23 ответа

Проблемы популярных подходов

Большинство ответов, которые вы найдете в Интернете, предложат вам либо установить зависимость для вашего локального репозитория, либо указать "системную" область в pom и распространите зависимость с источником вашего проекта. Но оба эти решения на самом деле несовершенны.

Почему вы не должны применять подход "Install to Local Repo"

Когда вы устанавливаете зависимость в свой локальный репозиторий, он остается там. С вашим артефактом распространения все будет хорошо, если у него есть доступ к этому хранилищу. Проблема в том, что в большинстве случаев этот репозиторий будет находиться на вашем локальном компьютере, поэтому не будет никакого способа разрешить эту зависимость на любом другом компьютере. Очевидно, что зависимость вашего артефакта от конкретной машины - это не способ справиться с ситуацией. В противном случае эта зависимость должна быть установлена ​​локально на каждой машине, работающей с этим проектом, что не лучше.

Почему вы не должны применять подход "Scope System"

Банки, от которых зависит подход System Scope, не устанавливаются ни в какое хранилище и не присоединяются к целевым пакетам. Вот почему ваш дистрибутив не сможет решить эту зависимость при использовании. Именно это, я считаю, и стало причиной того, что использование системного объема даже не рекомендуется. В любом случае, вы не хотите полагаться на устаревшую функцию.

Статическое решение для репозитория в проекте

После помещения этого в ваш 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 будет включать следующее местоположение в директорию вашего проекта при поиске артефактов:

repo/
| - x/
|   | - y/
|   |   | - z/
|   |   |   | - ${artifactId}/
|   |   |   |   | - ${version}/
|   |   |   |   |   | - ${artifactId}-${version}.jar

Подробнее об этом вы можете прочитать в этом блоге.

Используйте Maven для установки в репозиторий проекта

Вместо того, чтобы создавать эту структуру вручную, я рекомендую использовать плагин Maven для установки ваших jar-файлов в качестве артефактов. Итак, чтобы установить артефакт в репозиторий в проекте под 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>

Вспомогательный скрипт

Поскольку выполнение команды установки для каждой библиотеки является раздражающим и определенно подверженным ошибкам, я создал служебный скрипт, который автоматически устанавливает все файлы jar из lib папка в хранилище проекта, автоматически разрешая все метаданные (groupId, artifactId и т. д.) из имен файлов. Сценарий также распечатывает зависимости xml для вас, чтобы скопировать и вставить в ваш pom,

Включите зависимости в ваш целевой пакет

Когда вы создадите свой репозиторий в проекте, вы решите проблему распределения зависимостей проекта с его источником, но с тех пор целевой артефакт вашего проекта будет зависеть от неопубликованных jar-файлов, поэтому при установке у этого хранилища будут неразрешимые зависимости.

Чтобы преодолеть эту проблему, я предлагаю включить эти зависимости в ваш целевой пакет. Это вы можете сделать либо с плагином сборки, либо лучше с плагином OneJar. Официальную документацию по OneJar легко понять.

Только для выброшенного кода

установить область видимости == и просто создать идентификатор группы, идентификатор артефакта и версию

<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)

Вы можете создать локальный репозиторий на вашем проекте

Например, если у вас есть 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

Примечание. При использовании области действия системы ( как упомянуто на этой странице) Maven нужны абсолютные пути.

Если ваши файлы находятся в корне вашего проекта, вам нужно добавить префикс значений systemPath к ${basedir}.

Это то, что я сделал, он также работает с проблемой пакета и работает с проверенным кодом.

Я создал новую папку в проекте, в моем случае я использовал 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>

Вот как мы добавляем или устанавливаем локальную банку

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

я дал некоторые значения по умолчанию groupId и artifactId, потому что они являются обязательными:)

Вы действительно должны установить фреймворк через репозиторий и заранее определить ваши зависимости. Использование системной области является распространенной ошибкой, которую используют люди, потому что они "не заботятся об управлении зависимостями". Проблема в том, что, делая это, вы получаете извращенную сборку maven, которая не будет отображать maven в нормальном состоянии. Тебе лучше следовать такому подходу.

Плагин установки Maven использует командную строку для установки jar в локальный репозиторий, POM является необязательным, но вам нужно будет указать GroupId, ArtifactId, Version и Packaging (все содержимое POM).

С помощью <scope>system</scope> Это ужасная идея по причинам, объясненным другими, установка файла вручную в локальный репозиторий делает сборку невоспроизводимой и использует <url>file://${project.basedir}/repo</url> это тоже не очень хорошая идея, потому что (1) это может быть file URL (например, если проект извлечен в каталоге с необычными символами), (2) результат будет неприменим, если POM этого проекта используется в качестве зависимости от чужого проекта.

Если вы не хотите загружать артефакт в общедоступный репозиторий, предложение Симеона о вспомогательном модуле делает эту работу. Но теперь есть более легкий путь...

Рекомендация

Используйте https://github.com/stephenc/non-maven-jar-maven-plugin. Делает именно то, что вы просили, без каких-либо недостатков других подходов.

Я нашел другой способ сделать это, см. Здесь из сообщения Heroku

Подводя итог (извините за некоторые скопировать и вставить)

  • Создать repo каталог под вашей корневой папкой:
yourproject
+- pom.xml
+- источник
+- репо
  • Запустите это, чтобы установить jar в локальный каталог репо
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
  • Добавьте это ваше pom.xml:
<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>

То, что мне кажется самым простым, - это просто настроить плагин maven-compiler-plugin, чтобы он включал ваши пользовательские файлы jar. Этот пример загрузит любые файлы jar в каталог lib.

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <includes>
                    <include>lib/*.jar</include>
                </includes>
            </configuration>
        </plugin>

После продолжительного обсуждения с ребятами из CloudBees правильной упаковки таких 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) (упаковка POM)

JAR 1 обертка Maven, детский проект (упаковка POM)

JAR 2 обертка Maven, детский проект (упаковка POM)

основной существующий детский проект Maven (WAR, JAR, EAR .... упаковка)

Когда родительский процесс выполняется через mvn:install или mvn:package принудительно, и субмодули будут выполнены. Это может рассматриваться как минус, так как структура проекта должна быть изменена, но в конце предлагает нестатическое решение.

Чтобы установить сторонний jar, которого нет в репозитории maven, используйте maven-install-plugin.

Ниже приведены шаги:

  1. Скачать JAR-файл вручную с источника (веб-сайт)
  2. Создайте папку и поместите в нее свой файл jar
  3. Запустите приведенную ниже команду, чтобы установить сторонний 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-Rolling-Appender -Dversion=20150607-2059 -Dpackaging= баночка

  1. В pom.xml включите зависимость как показано ниже

      <dependency> 
            <groupId>uk.org.simonsite</groupId>
            <artifactId>log4j-rolling-appender</artifactId>
            <version>20150607-2059</version> 
      </dependency>
    
  2. Запустите команду mvn clean install, чтобы создать упаковку

Ниже ссылка ссылка:

https://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html

Если вы хотите быстрое и грязное решение, вы можете сделать следующее (хотя я не рекомендую это ни для чего, кроме тестовых проектов, maven долго будет жаловаться, что это не правильно).

Добавьте запись о зависимости для каждого необходимого вам jar-файла, желательно с помощью perl-скрипта или чего-то подобного, и скопируйте / вставьте его в ваш pom-файл.

#! /usr/bin/perl

foreach my $n (@ARGV) {

    $n=~s@.*/@@;

    print "<dependency>
    <groupId>local.dummy</groupId>
    <artifactId>$n</artifactId>
    <version>0.0.1</version>
    <scope>system</scope>
    <systemPath>\${project.basedir}/lib/$n</systemPath>
</dependency>
";

Быстрое и грязное пакетное решение (на основе ответа Алекса):

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 и скопируйте его содержимое как зависимости.

В моем случае мне нужны были только библиотеки для компиляции моего кода, и это решение было лучшим для этой цели.

Проблема с systemPath заключается в том, что файлы jar зависимостей не будут распределяться по вашим артефактам как переходные зависимости. Попробуйте то, что я написал здесь: лучше ли Mavenize файлы вашего проекта JAR или поместить их в WEB-INF/lib?

Затем объявите зависимости как обычно.

И, пожалуйста, прочитайте примечание нижнего колонтитула.

Даже если это не совсем подходит к вашей проблеме, я опущу это здесь. Мои требования были:

  1. Банки, которые не могут быть найдены в онлайн-хранилище maven, должны быть в SVN.
  2. Если один разработчик добавляет другую библиотеку, другим разработчикам не следует беспокоиться об их ручной установке.
  3. Среда IDE (в моем случае NetBeans) должна найти источники и javadoc для автозаполнения и помощи.

Давайте сначала поговорим о (3): просто держать банки в папке и как-то объединять их в финальную банку здесь не сработает, поскольку среда IDE не поймет этого. Это означает, что все библиотеки должны быть установлены правильно. Однако я не хочу, чтобы все устанавливали его с помощью "mvn install-file".

В моем проекте мне понадобился мета-виджет. Вот так:

  1. Создайте новый проект Maven (назовите его "shared-libs" или что-то в этом роде).
  2. Скачайте metawidget и распакуйте zip в src / main / lib.
  3. Папка doc / api содержит Javadocs. Создайте ZIP-архив содержимого (doc / api / api.zip).
  4. Модифицируйте пом как это
  5. Постройте проект, и библиотека будет установлена.
  6. Добавьте библиотеку в качестве зависимости к вашему проекту или (если вы добавили зависимость в проекте shared-libs) добавьте shared-libs в качестве зависимости, чтобы получить все библиотеки одновременно.

Каждый раз, когда у вас есть новая библиотека, просто добавьте новое исполнение и скажите всем, что вам нужно построить проект заново (вы можете улучшить этот процесс с помощью иерархий проектов).

Странное решение, которое я нашел:

используя Eclipse

  • создать простой (не maven) проект Java
  • добавить основной класс
  • добавить все банки в путь к классам
  • экспорт Runnable JAR (это важно, потому что здесь нет другого способа сделать это)
  • выберите Извлечь необходимые библиотеки в сгенерированный JAR
  • решить вопросы лицензии
  • tadammm... установите сгенерированную банку на свой m2repo
  • добавьте эту единственную зависимость к другим вашим проектам.

ура, Балинт

Для тех, кто не нашел здесь хорошего ответа, это то, что мы делаем, чтобы получить банку со всеми необходимыми зависимостями. В этом ответе ( /questions/13896682/mogu-li-ya-dobavit-fajlyi-jar-v-maven-2-buildpath-bez-ih-ustanovki/13896699#13896699) упоминается использование подключаемого модуля 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>

Я сослался на некоторый код на python в комментарии к ответу @alex lehmann's, поэтому выкладываю его здесь.

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

В нашем проекте работает то, что написал Архимед Траяно, но в нашем файле.m2/settings.xml было что-то вроде этого:

 <mirror>
  <id>nexus</id>
  <mirrorOf>*</mirrorOf>
  <url>http://url_to_our_repository</url>
 </mirror>

и * следует изменить на центральный. Так что, если его ответ не работает для вас, вы должны проверить свои settings.xml

Это не ответ на вопрос о том, как добавить их в POM, и, может быть, не составит труда, но просто добавит lib dir к вашей работе с classpath? Я знаю, что это то, что я делаю, когда мне нужна внешняя банка, которую я не хочу добавлять в свои репозитории Maven.

Надеюсь это поможет.

Решение для подхода scope='system' в Java:

public static void main(String[] args) {
        String filepath = "/Users/Downloads/lib/";
        try (Stream<Path> walk = Files.walk(Paths.get(filepath))) {

        List<String> result = walk.filter(Files::isRegularFile)
                .map(x -> x.toString()).collect(Collectors.toList());

                String indentation = "    ";
                for (String s : result) {
                    System.out.println(indentation + indentation + "<dependency>");
                    System.out.println(indentation + indentation + indentation + "<groupId>"
                            + s.replace(filepath, "").replace(".jar", "")
                            + "</groupId>");
                    System.out.println(indentation + indentation + indentation + "<artifactId>"
                            + s.replace(filepath, "").replace(".jar", "")
                            + "</artifactId>");
                    System.out.println(indentation + indentation + indentation + "<version>"
                            + s.replace(filepath, "").replace(".jar", "")
                            + "</version>");
                    System.out.println(indentation + indentation + indentation + "<scope>system</scope>");
                    System.out.println(indentation + indentation + indentation + "<systemPath>" + s + "</systemPath>");
                    System.out.println(indentation + indentation + "</dependency>");
                }

    } catch (IOException e) {
        e.printStackTrace();
    }
}

Я просто хотел быстрый и грязный обходной путь... Я не мог запустить скрипт от Никиты Волкова: синтаксическая ошибка + требуется строгий формат для имен банок.

Я создал этот Perl-скрипт, который работает с любым форматом для имен файлов jar, и он генерирует зависимости в xml, чтобы его можно было копировать и вставлять непосредственно в pom.

Если вы хотите использовать его, убедитесь, что вы понимаете, что делает скрипт, вам может потребоваться изменить 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;
Другие вопросы по тегам