Есть ли способ исключить артефакты, унаследованные от родительского POM? - PullRequest
100 голосов
/ 21 апреля 2010

Артефакты из зависимостей можно исключить, объявив элемент <exclusions> внутри <dependency> Но в этом случае необходимо исключить артефакт, унаследованный от родительского проекта. Ниже приводится выдержка из обсуждаемого ПОМ:

<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, существующим в родительском объекте, который ограничен compile.

Решением может быть удаление mail.jar из родительского POM, но большинству проектов, которые наследуют base, это нужно (так как это транзитивная зависимость для log4j). Поэтому я хотел бы просто исключить родительскую библиотеку из дочернего проекта , как это могло бы быть сделано, если бы base была зависимостью, а не родительским pom:

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

Ответы [ 8 ]

40 голосов
/ 21 апреля 2010

Некоторые идеи:

  1. Возможно, вы просто не могли бы наследовать от родителя в этом случае (и объявить зависимость от base с исключением). Не удобно, если у вас много вещей в родительском пом.

  2. Еще одна вещь, которую нужно проверить, - это объявить артефакт mail с версией, необходимой для ALL-DEPS в dependencyManagement в родительской поме, чтобы вызвать сходимость (хотя я не уверен, что это решит проблема определения объема).

<dependencyManagement>
  <dependencies>
    <dependency>    
      <groupId>javax.mail</groupId>
      <artifactId>mail</artifactId>
      <version>???</version><!-- put the "right" version here -->
    </dependency>
  </dependencies>
</dependencyManagement>
  1. Или вы можете исключить зависимость 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. Или вы можете вернуться к версии 1.2.14 log4j вместо еретической версии 1.2.15 (почему они не пометили вышеуказанные зависимости как необязательно ?!).
23 голосов
/ 12 ноября 2013

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

и ссылаться на них из вашей родительской помпы (смотрите зависимость <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>

Ваш дочерний проект наследует этот родительский pom, как и раньше. Но теперь почтовую зависимость можно исключить в дочернем проекте в блоке 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>
7 голосов
/ 05 января 2018

Переопределить зависимость (в дочернем pom) с помощью системы scope, указывающей на пустой jar:

<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
7 голосов
/ 22 декабря 2017

Не используйте родительский помпон

Это может звучать экстремально, но точно так же «адский наследство» является причиной, по которой некоторые люди отворачиваются от объектно-ориентированного программирования, или таким же образом, как хирурги поддерживают вас при коронарном шунтировании: удалите проблемный блок <parent> и скопируйте и вставьте все, что вам нужно <dependencies> 1007 *

Предположение о том, что разделение poms на родителя и ребенка для «повторного использования» и «избежания избыточности» должно быть проигнорировано, и вы должны в первую очередь удовлетворить ваши насущные потребности. Избыточность имеет свои преимущества, а именно - независимость от внешних осложнений.

Это проще, чем кажется, если вы генерируете эффективный pom (eclipse предоставляет его, но вы можете генерировать его из командной строки).

Пример

Я хочу использовать logback, но мой родительский pom использует log4j, и я не хочу идти и вынужден вставлять зависимость других детей от log4j в их собственные pom.xml файлы, чтобы мои не были беспрепятственными.

Вы можете многое получить от родителей, но иногда ваш родитель не знает, что для вас хорошо.

6 голосов
/ 22 апреля 2010

Вы пытались явно объявить версию 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>
3 голосов
/ 30 октября 2012

Лучше всего сделать зависимости, которые вы не всегда хотите наследовать, непереходными.

Вы можете сделать это, пометив их в родительском помпоне с предоставленной областью действия.

Если вы все еще хотите, чтобы родитель управлял версиями этих deps, вы можете использовать тег <dependencyManagement> для установки нужных версий без явного их наследования или передачи наследства дочерним элементам.

1 голос
/ 03 мая 2019

Мне действительно нужно было сделать эту грязную вещь ... Вот как

Я переопределил эти зависимости с областью действия test. Сфера provided не работает для меня.

Мы используем плагин Spring Boot для создания толстой банки. У нас есть модуль common , который определяет общие библиотеки, например Springfox swagger-2. Мой супер-сервис должен иметь родителя common (он этого не хочет, но правила компании действуют!)

Итак, у моих родителей или людей есть пом.

<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

Также стоит упомянуть этот ответ - я хотел это сделать, но мне лень ... https://stackoverflow.com/a/48103554/4587961

1 голос
/ 07 июня 2016

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

...