web-dev-qa-db-fra.com

Est-il possible d'exclure des artefacts hérités d'un POM parent?

Les artefacts de dépendances peuvent être exclus en déclarant un <exclusions> élément dans un <dependency> Mais dans ce cas, il est nécessaire d'exclure un artefact hérité d'un projet parent. Un extrait du POM en discussion suit:

<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 artefact, dépend de javax.mail:mail-1.4.jar, et ALL-DEPS dépend d'une autre version de la même bibliothèque. À cause du fait que mail.jar de ALL-DEPS _ existe dans l’environnement d’exécution, bien que non exporté, entre en conflit avec le mail.jar qui existe sur le parent et qui est défini comme compile.

Une solution pourrait consister à supprimer mail.jar du POM parent, mais la plupart des projets qui héritent de la base en ont besoin (tout comme une dépendance transtive pour log4j). Donc, ce que je voudrais faire est de simplement exclure la bibliothèque du parent du projet enfant, comme cela pourrait être fait si base était une dépendance et non le pom parent:

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

Quelques idées:

  1. Dans ce cas, vous pourriez peut-être simplement pas hériter du parent (et déclarer une dépendance sur base avec l'exclusion). Pas pratique si vous avez beaucoup de choses dans le pom parent.

  2. Une autre chose à tester serait de déclarer l'artefact mail avec la version requise par ALL-DEPS sous dependencyManagement dans le pom parent pour forcer la convergence (bien que je ne sois pas sûr que cela résoudra le problème de la portée).

<dependencyManagement>
  <dependencies>
    <dependency>    
      <groupId>javax.mail</groupId>
      <artifactId>mail</artifactId>
      <version>???</version><!-- put the "right" version here -->
    </dependency>
  </dependencies>
</dependencyManagement>
  1. Ou vous pouvez exclure la dépendance mail de log4j si vous n'utilisez pas les fonctionnalités qui en dépendent (et c'est ce que je ferais):
<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. Ou vous pouvez revenir à la version 1.2.14 de log4j au lieu de la version hérétique 1.2.15 (pourquoi n’ont-ils pas marqué les dépendances ci-dessus comme facultatif ?!).
40
Pascal Thivent

Vous pouvez regrouper vos dépendances dans un projet différent avec le package pom décrit dans 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>

et référencez-les à partir de votre parent-pom (regardez la dépendance <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>

Votre projet-enfant hérite de ce parent-pom comme auparavant. Mais maintenant, la dépendance de messagerie peut être exclue dans le projet enfant dans le bloc 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>
23
timomeinen

Ne pas utiliser un pom parent

Cela peut sembler extrême, mais de la même manière "l'enfer de l'héritage" est une raison pour laquelle certaines personnes tournent le dos à la programmation orientée objet, suppriment la problématique <parent> block et copier/coller peu importe <dependencies> vous avez besoin.

L'hypothèse selon laquelle le fractionnement de poms en un parent et un enfant pour "réutilisation" et "éviter la redondance" doit être ignorée et vous devez répondre d'abord à vos besoins immédiats. Le "remède" est pire que la maladie. En outre, la redondance a ses avantages, à savoir l’indépendance des modifications externes (stabilité).

C’est plus facile que cela ne paraisse si vous générez le pom effectif (Eclipse le fournit, mais vous pouvez le générer à partir de la ligne de commande avec mvn help:effective).

Exemple

Je veux utiliser logback comme ma liaison slf4j, mais mon pom parent inclut le log4j dépendance. Je ne veux pas y aller et je dois enfoncer la dépendance des autres enfants envers log4j dans leur propre pom.xml fichiers pour que le mien ne soit pas obstrué.

9
Sridhar Sarnobat

Redéfinissez la dépendance (dans le pom enfant) avec le système scope pointant vers un fichier jar vide:

<dependency>
    <groupId>dependency.coming</groupId>
    <artifactId>from.parent</artifactId>
    <version>0</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/empty.jar</systemPath>
</dependency>

Le fichier jar ne peut contenir qu'un seul fichier vide:

touch empty.txt
jar cvf empty.txt
7
Bax

Avez-vous essayé de déclarer explicitement la version de mail.jar que vous voulez? La résolution de dépendance de Maven devrait utiliser ceci pour la résolution de dépendance sur toutes les autres versions.

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

Le mieux est de créer des dépendances dont vous ne voulez pas toujours hériter de manière intransitive.

Vous pouvez le faire en les marquant dans le pom parent avec la portée fournie.

Si vous voulez toujours que le parent gère les versions de ces dépôts, vous pouvez utiliser le <dependencyManagement> balise pour configurer les versions de votre choix sans les hériter explicitement, ni transmettre cet héritage aux enfants.

3
Ajax

Lorsque vous appelez un paquet mais ne voulez pas certaines de ses dépendances, vous pouvez faire une chose comme celle-ci (dans ce cas, je ne voulais pas que l'ancien log4j soit ajouté parce que je devais utiliser le plus récent):

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

Cela fonctionne pour moi ... mais je suis assez nouveau pour Java/maven, donc ce n’est peut-être pas optimal.

1
bastienb1991

J'avais vraiment besoin de faire cette sale chose ... Voici comment

J'ai redéfini ces dépendances avec scope test. Scope provided n'a pas fonctionné pour moi.

Nous utilisons un plugin Spring Boot pour construire un pot de graisse. Nous avons le module common qui définit les bibliothèques communes, par exemple Springfox swagger-2. Mon super-service doit avoir un parent commun (il ne veut pas de le faire, mais les règles de la compagnie en vigueur!)

Donc, mes parents ou communes ont pom.

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

Et mon super-service pom.

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

C'est la taille de l'artefact gras final

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

Aussi cette réponse mérite d'être mentionnée - je voulais le faire, mais je suis paresseux ... https://stackoverflow.com/a/48103554/4587961

1
Yan Khonski