Есть ли вообще исключить артефакты, унаследованные от родительского ПОМ?

Артефакты из зависимостей можно исключить, объявив элемент <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

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

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

  2. Еще одна вещь, которую нужно проверить, - объявить артефакт 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>
  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 (почему они не отметили вышеуказанные зависимости как необязательные?!).

Ответ 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/...