Несколько версий одной и той же зависимости в Maven
Можно ли объявить несколько версий одной и той же зависимости в репозитории Maven?
Мне нужны эти зависимости сразу:
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.7.9-R0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.7.2-R0.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.6.4-R2.0</version>
<scope>compile</scope>
</dependency>
Поскольку каждый из них содержит другой пакет, о котором я забочусь:
org.bukkit.craftbukkit.v1_6_R3
org.bukkit.craftbukkit.v1_7_R1
org.bukkit.craftbukkit.v1_7_R3
Если я объявляю зависимости, как показано в первом фрагменте, вступает в силу только последний. Есть ли способ достичь этого в Maven?
@Edit Любое обходное решение, возможно?
Ответы
Ответ 1
Нет. Maven разрешит только одну зависимость в вашем модуле и опустит другие версии, чтобы избежать конфликта. Даже если несколько версий одной и той же зависимости используются во всей иерархии зависимостей, Maven выберет одну версию, используя стратегию "ближайшего в дереве зависимостей".
Можно указать разные версии зависимостей, используя различные profiles. Для каждой версии Bukkit можно определить и активировать профиль. Тем не менее, если вы активируете более одного профиля, будет использоваться только одна версия.
<profiles>
<profile>
<id>Bukkit_1_7_9_R02</id>
<activation>
...
</activation>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.7.9-R0.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
</profile>
<profile>
<id>Bukkit_1_7_2_R03</id>
<activation>
...
</activation>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.7.2-R0.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
</profile>
...
</profiles>
Ответ 2
Нет, вы не можете полагаться на 2 версии одного и того же артефакта, как правило.
Но вы можете включить их, чтобы они оказались в конечном приложении.
Это требование иногда справедливо, например, когда обслуживание этой библиотеки плохое, и они переименовывают некоторые пакеты и выпускают их как вспомогательную версию того же артефакта. Тогда другие проекты имеют его как стороннюю зависимость и нуждаются в одних и тех же классах под разными FQCN.
В таких случаях вы можете, например, использовать maven-shade-plugin
.
- Создайте проект maven с одной зависимостью, одной из нужных вам версий.
- Добавьте
shade
плагин и пусть это создать тенистую банку. Это будет в основном переупаковывать классы под другим артефактом G: A: V. - Сделайте это для всех версий, которые вам нужны.
- Вы можете использовать классификатор, чтобы различать затененные версии.
- В вашем проекте зависят от этих артефактов.
- Наконец, исключите исходные зависимости, дайте им область "предоставлено".
Вы можете использовать разные варианты одного и того же, что в итоге поместит эти классы в ваш путь к классам. Например, используйте плагин/цель dependency:copy-dependency
и установите этот jar файл в локальный репозиторий во время сборки. Или распакуйте классы прямо в ваш ${project.build.outputDirectory}
(target/classes).
Ответ 3
Я все еще довольно новый, но кое-что, с чем я столкнулся с осью 2, заключается в том, что для отдельных модулей иногда требуется более ранняя версия из-за изменений, внесенных ими в классы, поэтому зависимость верхнего уровня улавливает почти половину их. В остальном мне пришлось индивидуально корректировать poms для явных зависимостей для другой версии.
Возможно, этот подход будет работать и на вас? Наличие плагина имеет модульные компоненты для их конкретных зависимостей.
Ответ 4
Вот сценарий, где это может быть проблемой, когда maven рассматривает только один экземпляр зависимости.
Проект зависит от двух других проектов, и в свою очередь оба других проекта зависят от третьего проекта, но разные подмножества (т.е. исключают).
Желаемый эффект заключается в том, что окончательный проект включает объединенное подмножество, но на самом деле он будет включать только одно подмножество.
В большом проекте вполне возможно, что существуют зависимости в форме алмаза. В этом случае вы должны быть очень осторожны при использовании исключений.
Ответ 5
Попробуй обмануть мавена
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.7.9-R0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.bukkit.</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.7.2-R0.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.bukkit..</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.6.4-R2.0</version>
<scope>compile</scope>
</dependency>
Ответ 6
Вот как я обошел это. К вашему сведению: в моем случае я строил RPM.
Я использовал maven-dependency-plugin
чтобы скопировать старую зависимость, которая игнорируется, в папку в каталоге сборки, а затем скопировал этот файл в промежуточную область, чтобы включить его в RPM.
Вот код для копирования старой зависимости:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>some.package.group.id</groupId>
<artifactId>someartifact-id</artifactId>
<version>1.2.3</version>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/older-dependencies</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
А потом позже, во время сборки моего RPM, я включил этот скриптлет в раздел configuration
моего rpm-maven-plugin
. Это скопирует файл в промежуточную область для RPM:
<installScriptlet>
<script>cp ${project.build.directory}/older-dependencies/* ${project.build.directory}/rpm/${artifactId}/buildroot${installBase}/</script>
</installScriptlet>