Maven Shaded Jar используется в качестве внешней зависимости проекта

Я использовал плагин maven shade в своем проекте, чтобы переместить все jar-классы зависимостей в один пакет, например org.shade. *

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

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

2 ответа

Решение

Классический сценарий:

  • Проект, производящий uber-jar, имеет свои зависимости (dependency элементы в его pom.xml файл), которые затем упакованы в один супер-jar как артефакт Maven
  • При использовании этого uber-jar в качестве зависимости (dependency элемент) другого проекта, Maven будет затем проверять его <artifact>-<version>.pom файл (опубликованный вместе с последним артефактом в хранилище Maven), который в основном является переименованной копией оригинала pom.xml файл, где зависимости (dependency элемент) были объявлены (именно зависимости, упакованные в uber-jar).
  • Так как вы уже собрали их, вам следует игнорировать .pom файл (и его dependencies элемент), для этого нужно добавить exclusions следующим образом:

    <dependency>
        <groupId>com.sample</groupId>
        <artifactId>something-uber</artifactId>
        <version>some-version</version>
        <exclusions>
            <exclusion>
                <groupId>*</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    

Примечание: вышеуказанная функция доступна только с Maven 3.2.1,

Таким образом, вы даете понять Maven, что не хотите никакой транзитивной зависимости, и посредничество с зависимостями Maven не вызовет их.


В качестве примечания: не рекомендуется использовать Uber-jar в качестве зависимости проекта: это только усложнит обслуживание, поскольку вы не можете управлять переходными зависимостями с помощью dependencyManagement или же dependencies заказ зависимого проекта. Таким образом, вам всегда нужно будет повторно упаковать uber jar всякий раз, когда зависимость (одна из ее переходных) будет нуждаться в обслуживании (изменение версии и т. Д.) И иметь гораздо меньший контроль над зависимым проектом (опять же, более сложное обслуживание).


Поскольку файл pom.xml в вашем исходном проекте, который создает jar-файл uber, объявляет транзитивные зависимости, если вы включите его в качестве зависимости во внешний проект, Maven попытается получить их (даже если они уже включены в uber jar).

Я разделяю решение, которое позволяет вам избегать явного исключения всех транзитивных зависимостей, в том числе его, во внешний проект, как объяснил @A_DiMatteo в своем решении (я также согласен с ним относительно того, чтобы избегать использования uber jar в качестве зависимости, если в этом нет особой необходимости) по какой-то причине). В результате вы сможете включить свою зависимость от Uber JAR без использования элемента исключения, как показано ниже:

<dependency>
  <groupId>com.sample</groupId>
  <artifactId>something-uber</artifactId>
  <version>some-version</version>
</dependency>

Предпосылка: моя цель состояла в том, чтобы предоставить как uber (без транзитивной зависимости, объявленной для pom), так и тонкие jar-файлы для моего хранилища. Таким образом, мое решение "А" основано на этом сценарии и в настоящее время имеет ограничение, которое затененная банка загружается 2 раза в хранилище.

  • Чтобы обеспечить только Uber JAR см. Решение "B" ниже
  • Для возможного решения для предела "A" см. Раздел ОБНОВЛЕНИЕ в конце

А) Предоставить как тонкие, так и супер-банки в хранилище

1- В исходном проекте настройте на своем модуле что-то pom.xml следующий maven-shade-plugin следующим образом:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>2.2</version>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
      <configuration>
        <finalName>something-uber-${project.version}</finalName>
      </configuration>
    </execution>
  </executions>
</plugin>

Затем используйте плагин build-helper-maven-plugin, чтобы прикрепить новый артефакт с классификатором "uber" к модулю:

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>build-helper-maven-plugin</artifactId>
  <version>1.2</version>
  <executions>
    <execution>
      <id>attach-artifacts</id>
      <phase>package</phase>
      <goals>
        <goal>attach-artifact</goal>
      </goals>
      <configuration>
        <artifacts>
          <artifact>
            <file>
              ${project.build.directory}/something-uber-${project.version}.jar
            </file>
            <classifier>uber</classifier>
          </artifact>
        </artifacts>
      </configuration>
    </execution>
  </executions>
</plugin>

В результате этапа установки maven будут сгенерированы следующие два файла jar для target / directory:

40K something-0.1.0.jar
7M  something-uber-0.1.0.jar

ПРЕДУПРЕЖДЕНИЕ: после выполнения фазы развертывания maven оба файла jar будут загружены в хранилище! Цель здесь должна состоять в том, чтобы выгрузить только развертывание с пропуском тонкой банки для затененной банки, чтобы оставить его в качестве локального артефакта (см. Раздел ОБНОВЛЕНИЕ в конце для возможного исправления)

2- Создайте тогда другой модуль в вашем исходном проекте с именем some-uber, добавив следующие зависимости и плагин:

<dependencies>
    <dependency>
        <groupId>com.sample</groupId>
        <artifactId>something</artifactId>
        <version>${project.version}</version>
        <classifier>uber</classifier>
        <exclusions>
            <exclusion>
                <artifactId>*</artifactId>
                <groupId>*</groupId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.2</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Обратите внимание на следующие сведения о включении зависимости:

  • классификатор должен быть равен uber (тот, который вы указали, прикрепляя новый артефакт с помощью build-helper-maven-plugin в первом модуле)
  • исключения уточняются.

В конце этапа развертывания maven на этом модуле затененный jar будет загружен в хранилище, и вы сможете добавить его в качестве зависимости во внешний проект следующим образом:

<dependency>
 <groupId>com.sample</groupId>
 <artifactId>something-uber</artifactId>
 <version>0.1.0</version>
</dependency>

Б) Предоставить только Uber JAR на хранилище

Начиная с решения "А", если вы хотите избежать предоставления тонкой фляги в репозитории, вам следует избегать в пункте 1 указывать finalName в конфигурации maven-shade-plugin, поэтому избегайте также плагин build-helper-maven- plugin, поскольку новый артефакт для прикрепления. Делая это, при развертывании модуля у вас будет только Uber JAR на цели / по умолчанию (без классификатора):

7M  something-0.1.0.jar

Вы также должны пропустить загрузку, в противном случае у вас также будут загружены две толстые фляги (что-то -0.1.0.jar и что-то - uber-0.1.0.jar). Для этого добавьте следующий плагин в тот же модуль:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-deploy-plugin</artifactId>
    <version>2.8.2</version>
    <configuration>
        <skip>true</skip>
    </configuration>
</plugin>

В конце пункта 2 просто избегайте указывать классификатор при добавлении зависимости следующим образом:

<dependencies>
 <dependency>
    <groupId>com.sample</groupId>
    <artifactId>something</artifactId>
    <version>${project.version}</version>
    <exclusions>
        <exclusion>
            <artifactId>*</artifactId>
            <groupId>*</groupId>
        </exclusion>
    </exclusions>
 </dependency>
</dependencies>

ОБНОВЛЕНИЕ: Пропустить первую затененную банку на решение А)

После некоторого безуспешного поиска решения я решил раскошелиться на плагин maven-deploy-plugin из GitHub и поработать над новой функцией, чтобы пропустить затененный jar, созданный в первом модуле, добавив плагин, настроенный следующим образом:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-deploy-plugin</artifactId>
  <version>3.0.0-SNAPSHOT</version>
  <configuration>
    <skipAttachedArtifacts>
      <artifact>
        <groupId>com.sample</groupId>
        <artifactId>something</artifactId>
        <version>${project.version}</version>
        <packaging>jar</packaging>
        <classifier>uber</classifier>
      </artifact>
    </skipAttachedArtifacts>
  </configuration>
</plugin>

В настоящее время с использованием плагина maven-deploy-plugin все артефакты исключаются из развертывания, в то время как цель здесь состоит в том, чтобы исключить только определенный. На своем форке я ввел параметр конфигурации "skipAttachedArtifacts", чтобы указать вложенные артефакты, которые нужно исключить из развертывания.

Вот ссылка на мой разветвленный проект на GitHub: https://github.com/gregorycallea/maven-deploy-plugin

Здесь ссылка вместо этого на запрос на отправку, который я отправил в проекте плагина apache: https://github.com/apache/maven-deploy-plugin/pull/3

Другие вопросы по тегам