Exclure toutes les dépendances transitives d'une seule dépendance

221

Dans Maven2, pour exclure une seule dépendance transitive, je dois faire quelque chose comme ceci:

<dependency>
  <groupId>sample.group</groupId>
  <artifactId>sample-artifactB</artifactId>
  <version>1</version>
   <exclusions>
     <exclusion>
       <groupId>sample.group</groupId>
       <artifactId>sample-artifactAB</artifactId>
     </exclusion>
   </exclusions>
</dependency>

Le problème avec cette approche est que je dois le faire pour chaque dépendance transitive apportée par sample-artifactB.

Existe-t-il un moyen d'utiliser une sorte de caractère générique pour exclure toutes les dépendances transitives à la fois au lieu d'une par une?

pbreault
la source
Parfois, il faut utiliser une dernière version de la bibliothèque, par exemple Spring 2.5.6, mais certaines autres dépendances incluent une version plus ancienne, par exemple struts2-spring-plugin (2.1.6) inclut Spring 2.5.3. Dans de tels scénarios, il est nécessaire d'exclure ou de remplacer la version.
Vinod Singh
1
Utilisez Ivy. Je rigole.
Jake Toronto

Réponses:

54

Pour maven2, il n'y a aucun moyen de faire ce que vous décrivez. Pour maven 3, il y en a. Si vous utilisez maven 3, veuillez voir une autre réponse à cette question

Pour maven 2, je recommanderais de créer votre propre pom personnalisé pour la dépendance qui a vos <exclusions>. Pour les projets qui doivent utiliser cette dépendance, définissez la dépendance sur votre pom personnalisé au lieu de l'artefact typique. Bien que cela ne vous permette pas nécessairement d'exclure toutes les dépendances transitives avec une seule <exclusion>, cela vous permet de n'avoir à écrire votre dépendance qu'une seule fois et tous vos projets n'ont pas besoin de maintenir de longues listes d'exclusion inutiles.

whaley
la source
12
Je recommanderais de ne pas créer votre propre pom pour contourner les exclusions. Cela rend votre build beaucoup moins portable et réduit la compréhension.
Brian Fox
1
Si vous ne regardez pas au-delà de la réponse acceptée: jira.codehaus.org/browse/MNG-3832
Jakub Bochenski
@JakubBochenski la réponse que j'ai donnée est spécifique à maven 2, qui est ce avec quoi cette question est étiquetée (au moment où j'ai écrit ce commentaire). Votre lien n'est pertinent que pour maven 3. Quoi qu'il en soit, j'ai modifié ma réponse pour créer un lien vers la réponse la plus votée.
whaley
306

Ce qui a fonctionné pour moi (peut-être une fonctionnalité plus récente de Maven) est simplement de faire des caractères génériques dans l'élément d'exclusion.

J'ai un projet multi-module qui contient un module "app" qui est référencé dans deux modules packagés WAR. L'un de ces modules fournis par WAR n'a vraiment besoin que des classes de domaine (et je ne les ai pas encore séparés du module d'application). J'ai trouvé que cela fonctionnait:

<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>app</artifactId>
    <version>${project.version}</version>
    <exclusions>
        <exclusion>
            <groupId>*</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Le caractère générique sur groupId et artifactId exclut toutes les dépendances qui se propageraient normalement vers le module à l'aide de cette dépendance.

enricopulatzo
la source
9
Le caractère générique * pour le groupe et l'artifact semble fonctionner dans le maven 3
nkr1pt
22
Je ne sais pas comment vous avez pu trouver ce fonctionnement, car Maven 3 avertit explicitement de l'utilisation de l'astérisque: [AVERTISSEMENT] 'dependencies.dependency.exclusions.exclusion.groupId' pour <artifcat_id> avec la valeur "*" ne le fait pas correspondre à un modèle d'ID valide. [AVERTISSEMENT] Il est fortement recommandé de résoudre ces problèmes car ils menacent la stabilité de votre build. [AVERTISSEMENT] Pour cette raison, les futures versions de Maven pourraient ne plus prendre en charge la création de tels projets malformés. Pourriez-vous fournir des preuves de sa prise en charge et de son utilisation? Sinon, je considérerais votre commentaire comme extrêmement trompeur.
2011 à 12h59
7
Fonctionne magnifiquement avec Maven 3.0.4. Merci beaucoup !
Evgeny Goldin
1
maven 3.0.4 -> cela n'a pas bien fonctionné pour moi. le pot résultant est très différent lorsque j'utilise Astérix, ou lorsque j'exclus explicitement toutes les dépendances directes. cela peut être lié au fait que j'utilise maven-assembly-plugin pour créer un gros pot. dans ce cas, la sulotion suggérée ne fonctionne pas!
gilad hoch
31
Cette méthode est valide. Ils ont corrigé l'avertissement que d'autres signalent dans maven 3.2.1: issues.apache.org/jira/browse/MNG-3832
Ryan
32

Une chose que j'ai trouvée utile:

Si vous placez la dépendance avec les exclusions dans la section dependencyManagement du POM parent de votre projet ou dans un POM de gestion des dépendances importable, vous n'avez pas besoin de répéter l'exclusion (ou la version).

Par exemple, si votre POM parent a:

<dependencyManagement>
    <dependencies>
    ...         
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.2.1</version>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
     ....
  </dependencies>
</dependencyManagement>

Ensuite, les modules de votre projet peuvent simplement déclarer la dépendance comme:

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
        </dependency>

Le POM parent spécifie à la fois la version et les exclusions. J'utilise cette technique pour presque tous nos projets et elle élimine beaucoup de répétitions.

Joshua Davis
la source
23

Il y a trois ans, j'ai recommandé d'utiliser la version 99 n'existe pas, mais maintenant j'ai trouvé un meilleur moyen, d'autant plus que la version 99 est hors ligne:

Dans le POM parent de votre projet, utilisez le plug-in maven -forcer pour échouer la génération si la dépendance indésirable se glisse dans la génération. Cela peut être fait en utilisant la règle des dépendances interdites du plugin :

<plugin>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>1.0.1</version>
    <executions>
        <execution>
            <id>only-junit-dep-is-used</id>
            <goals>
                <goal>enforce</goal>
            </goals>
            <configuration>
                <rules>
                    <bannedDependencies>
                        <excludes>
                            <exclude>junit:junit</exclude>
                        </excludes>
                    </bannedDependencies>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>

Ensuite, lorsque cela vous avertit d'une dépendance indésirable, excluez-la dans la <dependencyManagement>section du POM parent :

<dependency>
    <groupId>org.springframework.batch</groupId>
    <artifactId>spring-batch-test</artifactId>
    <version>2.1.8.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
    </exclusions>
</dependency>

De cette façon, la dépendance indésirable n'apparaîtra pas accidentellement (contrairement à un <exclusion>qui est facile à oublier), elle ne sera pas disponible même pendant la compilation (contrairement à la providedportée), il n'y a pas de dépendances bidon (contrairement à la version 99) et il ' ll fonctionne sans référentiel personnalisé (contrairement à la version 99). Cette approche fonctionnera même en fonction de la version de l'artefact, des classificateurs, de la portée ou de tout un groupId - voir la documentation pour plus de détails.

Esko Luontola
la source
Notez qu'au moins sous Maven 3.1, le <configuration>est ignoré lors de l'exécution de l'objectif à partir de la ligne de commande et doit être remonté directement sous <plugin>.
David Harkness
Je viens de trouver ce qui ressemble à un méchant bug Maven - version 3.5.2. J'ai un projet avec des sous-modules où j'exclus une dépendance à la <dependencyManagement>section des parents . L'exécution d'un mvn dependency:treedans ce projet spécifique n'aura pas du tout la dépendance exclue. Mais tous les projets qui importent cette dépendance n'honoreront pas le <exclusions>pom parent de l'autre projet - l'exclus se glissera dedans !!! J'ai dû passer <exclusions>directement à chaque module pom.
cbaldan
11

J'utilise la solution de contournement suivante: au lieu d'essayer d'exclure l'artefact dans toutes les dépendances appropriées, je dessine la dépendance comme "fournie" au niveau supérieur. Par exemple, pour éviter d'expédier xml-apis "quelle que soit la version":

    <dependency>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
        <version>[1.0,]</version>
        <scope>provided</scope>
    </dependency>
Michael Zilbermann
la source
9

Actuellement, il n'y a aucun moyen d'exclure plus d'une dépendance transitive à la fois, mais il existe une demande de fonctionnalité pour cela sur le site Maven JIRA:

https://issues.apache.org/jira/browse/MNG-2315

Peter
la source
6

Il existe une solution de contournement pour cela, si vous définissez la portée d'une dépendance sur runtime , les dépendances transitives seront exclues. Cependant, sachez que cela signifie que vous devez ajouter un traitement supplémentaire si vous souhaitez empaqueter la dépendance d'exécution.

Pour inclure la dépendance d'exécution dans n'importe quel package, vous pouvez utiliser l' objectif de copie du plug-in maven-dependency-plugin pour un artefact spécifique .

Vendeur riche
la source
1
Cela m'a aidé à contourner les problèmes avec le compilateur Android Dalvik qui ne pouvait pas gérer certaines des inclusions transitives à deux niveaux --- mais j'ai dû utiliser à la <scope>provided</scope>place de <scope>runtime</scope>.
Garret Wilson
6

si vous devez exclure toutes les dépendances transitives d'un artefact de dépendance que vous allez inclure dans un assembly, vous pouvez le spécifier dans le descripteur du plug-in d'assembly:

<assembly>
    <id>myApp</id>
    <formats>
        <format>zip</format>
    </formats>
    <dependencySets>
        <dependencySet>
            <useTransitiveDependencies>false</useTransitiveDependencies>
            <includes><include>*:struts2-spring-plugin:jar:2.1.6</include></includes>
        </dependencySet>
    </dependencySets>
</assembly>
Superole
la source
3

Si vous développez sous Eclipse, vous pouvez dans le graphique de dépendance de l'éditeur POM (onglets avancés activés) rechercher la dépendance que vous souhaitez exclure de votre projet, puis:

faites un clic droit dessus -> "Exclure Maven Artifact ..." et Eclipse fera l'exclusion pour vous sans avoir besoin de savoir sur quelle dépendance la bibliothèque est liée.

Tib
la source
notez que cela ne fonctionne que si vous utilisez le plugin m2eclipse
Nicolas Mommaerts
2

Quelle est votre raison d'exclure toutes les dépendances transitives?

S'il existe un artefact particulier (comme la journalisation des communs) que vous devez exclure de chaque dépendance, l' approche de la version 99 n'existe pas peut vous aider.


Mise à jour 2012: n'utilisez pas cette approche. Utilisez le plugin maven -forcer et les exclusions . La version 99 produit de fausses dépendances et le référentiel de la version 99 est hors ligne (il existe des miroirs similaires, mais vous ne pouvez pas non plus compter sur eux pour rester en ligne pour toujours; il est préférable d'utiliser uniquement Maven Central).

Esko Luontola
la source
1

Dans un problème similaire, j'avais la dépendance souhaitée déclarée avec la portée fournie. Avec cette approche, les dépendances transitives sont récupérées mais ne sont PAS incluses dans la phase de package, ce que vous voulez. J'aime aussi cette solution en termes de maintenance, car il n'y a pas de pom, ou pom personnalisé comme dans la solution de whaley, à entretenir; il vous suffit de fournir la dépendance spécifique dans le conteneur et de terminer

nkr1pt
la source
-2

Utilisez le dernier maven dans votre chemin de classe .. Il supprimera les artefacts en double et conservera le dernier artefact maven ..

Samraj
la source