Как создать артефакт JarJar'd с Maven, где использование артефакта не тянет транзитивные зависимости?

В настоящее время у меня есть библиотека тестирования Java, которая построена с Maven и распространяется как банку. Мой проект зависит от очень общей библиотеки (Objectweb ASM), и у меня возникли проблемы, когда более ранняя и несовместимая версия ASM уже находится в пути к классам. Таким образом, я начал использовать jarjar-maven-plugin, чтобы создать jar, переупаковывая ASM внутри, где он не может конфликтовать с другой версией ASM.

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

Однако, поскольку у моего проекта есть зависимости от компиляции в ASM, всякий раз, когда клиентский проект добавляет мою библиотеку, все транзитные зависимости также втягиваются. Итак, гипотетически, если они используют определенную версию ASM, и они также добавляют версию, на которую я полагаюсь на путь к классам, они имеют поведение undefined. Я бы хотел избежать этой ситуации и позволить клиентам зависеть от артефакта JarJar'd, не заставляя Maven сбрасывать транзитивные зависимости как неоправданно, так и потенциально опасно.

Как создать артефакт JarJar'd, на который пользователи могут зависеть, не вытягивая транзитивные зависимости?

Ответ 1

Я нашел решение этой проблемы, отбросив плагин jarjar-maven и вернувшись к плагину maven-shade. Это позволяет переупаковывать классы в пределах вашего собственного пространства имен, устанавливая основной класс банки и, в решающей степени, переписывая сгенерированный pom, чтобы не включать в себя связанные с компиляцией временные зависимости, которые теперь включены.

Часть моего pom.xml, которая получила это:

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

            <shadedArtifactAttached>false</shadedArtifactAttached>
            <createDependencyReducedPom>true</createDependencyReducedPom>

            <relocations>
                <relocation>
                    <pattern>org.objectweb.asm</pattern>
                    <shadedPattern>${repackage.base}.org.objectweb.asm</shadedPattern>
                </relocation>
            </relocations>
            <transformers>
                <transformer
                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                    <mainClass>${package.base}.my.MainClass</mainClass>
                </transformer>
            </transformers>
        </configuration>
    </execution>
</executions>

Важными частями этой конфигурации являются:

  • shadedArtifactAttached, который при установке на false означает, что заштрихованная банка заменит основной артефакт, который обычно создается. По умолчанию это значение false, но это стоит указать.
  • createDependencyReducedPom, который при установке в true означает, что когда развернутая или установленная затененная банка развернута, развернутый pom.xml не будет включать зависимостей области компиляции, которые были переупакованы в банку.
  • relocation Эти элементы определяют, как файлы в зависимостях переупаковываются в затененную банку. В приведенном выше примере любой класс, каноническое имя которого начинается с org.objectweb.asm, будет перемещен в ${package.base}.org.objectweb.asm, и, таким образом, если в банке будет упакован эквивалентный путь к файлу в банке.

В этой конфигурации при развертывании моего проекта, когда клиенты объявляют зависимость от компиляции в моем проекте, она только тянет затененную банку и не имеет транзитивных зависимостей.

Ответ 2

Попробуйте вместо этого попробовать maven-shade-plugin, который позволяет использовать все виды тонкого контроля.

Ответ 3

Возможно, установка атрибута <optional> будет работать в вашем случае. Указание в библиотеке java-тестирования pom. Пример:

  <dependencies>
    <dependency>
      <groupId>asm.group</groupId>
      <artifactId>asm</artifactId>
      <version>x.y</version>
      <optional>true</optional>
    </dependency>
    ...
  </dependencies>