Есть ли вообще исключить артефакты, унаследованные от родительского ПОМ?
Артефакты из зависимостей можно исключить, объявив элемент <exclusions>
внутри <dependency>
Но в этом случае ему нужно было исключить артефакт, унаследованный от родительского проекта. Ниже приводится выдержка из POM:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>jruby</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<artifactId>base</artifactId>
<groupId>es.uniovi.innova</groupId>
<version>1.0.0</version>
</parent>
<dependencies>
<dependency>
<groupId>com.liferay.portal</groupId>
<artifactId>ALL-DEPS</artifactId>
<version>1.0</version>
<scope>provided</scope>
<type>pom</type>
</dependency>
</dependencies>
</project>
base
артефакт, зависит от javax.mail:mail-1.4.jar
, а ALL-DEPS
зависит от другой версии той же библиотеки. Из-за того, что mail.jar
из ALL-DEPS
существует в среде выполнения, хотя и не экспортирован, сталкивается с mail.jar
который существует в родительском mail.jar
, который используется как compile
.
Решение может состоять в том, чтобы избавиться от mail.jar от родительского POM, но для большинства проектов, которые наследуют базу, это нужно (как и зависимость от transtive для log4j). Итак, я хотел бы просто исключить родительскую библиотеку из дочернего проекта, поскольку это можно сделать, если base
была зависимой, а не родительской помпой:
...
<dependency>
<artifactId>base</artifactId>
<groupId>es.uniovi.innova</groupId>
<version>1.0.0</version>
<type>pom<type>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
</exclusions>
</dependency>
...
Ответы
Ответ 1
Некоторые идеи:
-
Возможно, вы могли бы просто не наследовать от родителя в этом случае (и объявить зависимость от base
с исключением). Не удобно, если у вас много вещей в родительском помпе.
-
Еще одна вещь, которую нужно проверить, - объявить артефакт mail
с версией, требуемой ALL-DEPS
под управлением dependencyManagement
в родительском pom, чтобы заставить конвергенцию (хотя я не уверен, что это решит проблему определения области).
<dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>???</version><!-- put the "right" version here -->
</dependency>
</dependencies>
</dependencyManagement>
- Или вы можете исключить зависимость
mail
от log4j, если вы не используете функции, полагающиеся на нее (и это то, что я буду делать):
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
</dependency>
- Или вы можете вернуться к версии 1.2.14 log4j вместо еретической версии 1.2.15 (почему они не отметили вышеуказанные зависимости как необязательные?!).
Ответ 2
Вы можете сгруппировать вашу зависимость в рамках другого проекта с упаковкой pom
, как описано Sonatypes Best Practices:
<project>
<modelVersion>4.0.0</modelVersion>
<artifactId>base-dependencies</artifactId>
<groupId>es.uniovi.innova</groupId>
<version>1.0.0</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
</project>
и ссылаться на них из вашего parent-pom (смотрите зависимость <type>pom</type>
):
<project>
<modelVersion>4.0.0</modelVersion>
<artifactId>base</artifactId>
<groupId>es.uniovi.innova</groupId>
<version>1.0.0</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<artifactId>base-dependencies</artifactId>
<groupId>es.uniovi.innova</groupId>
<version>1.0.0</version>
<type>pom</type>
</dependency>
</dependencies>
</project>
Ваш дочерний проект наследует этот родительский помп как и прежде. Но теперь почтовую зависимость можно исключить в дочернем проекте в блоке dependencyManagement
:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>jruby</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<artifactId>base</artifactId>
<groupId>es.uniovi.innova</groupId>
<version>1.0.0</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<artifactId>base-dependencies</artifactId>
<groupId>es.uniovi.innova</groupId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Ответ 3
Не используйте родительский помпон
Это может показаться экстремальным, но точно так же "адский наследство" является причиной, по которой некоторые люди отказываются от объектно-ориентированного программирования (или предпочитают композицию наследованию), удаляют проблемный блок <parent>
и скопируйте и вставьте все, что вам нужно <dependencies>
(если ваша команда предоставит вам эту свободу).
Предположение о том, что расщепление помов на родителя и ребенка для "повторного использования" и "предотвращения избыточности" следует игнорировать, и вы должны в первую очередь удовлетворять свои насущные потребности (лекарство хуже, чем болезнь). Кроме того, избыточность имеет свои преимущества, а именно - независимость от внешних изменений (т.е. стабильность).
Это проще, чем кажется, если вы генерируете эффективный pom (Eclipse предоставляет его, но вы можете сгенерировать его из командной строки с помощью mvn help:effective
).
Пример
Я хочу использовать logback
в качестве привязки к slf4j, но мой родительский pom включает зависимость log4j
. Я не хочу идти и вынужден помещать зависимость других детей от log4j в их собственные файлы pom.xml
, чтобы мои не были беспрепятственными.
Ответ 4
Переопределите зависимость (в дочернем помпе) с системой scope
, указывающей на пустую банку:
<dependency>
<groupId>dependency.coming</groupId>
<artifactId>from.parent</artifactId>
<version>0</version>
<scope>system</scope>
<systemPath>${project.basedir}/empty.jar</systemPath>
</dependency>
В банке может содержаться только один пустой файл:
touch empty.txt
jar cvf empty.txt
Ответ 5
Вы пытались явно объявить версию mail.jar, которую хотите? Решение Maven для зависимостей должно использовать это для разрешения зависимостей во всех других версиях.
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>jruby</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<artifactId>base</artifactId>
<groupId>es.uniovi.innova</groupId>
<version>1.0.0</version>
</parent>
<dependencies>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>VERSION-#</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.liferay.portal</groupId>
<artifactId>ALL-DEPS</artifactId>
<version>1.0</version>
<scope>provided</scope>
<type>pom</type>
</dependency>
</dependencies>
</project>
Ответ 6
Лучше всего сделать зависимости, которые вы не всегда хотите наследовать, непереходными.
Вы можете сделать это, отметив их в родительском помпоне с предоставленной областью.
Если вы все еще хотите, чтобы родитель управлял версиями этих deps, вы можете использовать <dependencyManagement>
чтобы установить нужные версии без явного их наследования или передачи этого наследования дочерним элементам.
Ответ 7
Когда вы вызываете пакет, но не хотите каких-либо его зависимостей, вы можете сделать что-то вроде этого (в этом случае я не хочу, чтобы старый log4j добавлялся, потому что мне нужно было использовать новый):
<dependency>
<groupId>package</groupId>
<artifactId>package-pk</artifactId>
<version>${package-pk.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- LOG4J -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.5</version>
</dependency>
Это работает для меня... но я довольно новичок в java/maven, так что это, возможно, не оптимально.
Ответ 8
Мне действительно нужно было сделать эту грязную вещь... Вот как
Я переопределил эти зависимости с помощью test
. provided
объем не работал для меня.
Мы используем весенний плагин Boot для создания толстой банки. У нас есть модуль common, который определяет общие библиотеки, например Springfox swagger-2. У моего суперсервиса должен быть общий родитель (он не хочет этого делать, но действуют правила компании!)
Так что у моих родителей или общин есть пом.
<dependencyManagement>
<!- I do not need Springfox in one child but in others ->
<dependencies>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>${swagger.version}</version>
</dependency>
<!- All services need them ->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${apache.poi.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
И мой супер-сервисный пом.
<name>super-service</name>
<parent>
<groupId>com.company</groupId>
<artifactId>common</artifactId>
<version>1</version>
</parent>
<dependencies>
<!- I don't need them ->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-core</artifactId>
<version>2.8.0</version>
<scope>test</scope>
</dependency>
<!- Required dependencies ->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
</dependencies>
Это размер конечного жирового артефакта
82.3 MB (86,351,753 bytes) - redefined dependency with scope test
86.1 MB (90,335,466 bytes) - redefined dependency with scope provided
86.1 MB (90,335,489 bytes) - without exclusion
Также стоит упомянуть этот ответ - я хотел это сделать, но мне лень... fooobar.com/info/7370/...