Schließen Sie alle transitiven Abhängigkeiten einer einzelnen Abhängigkeit aus

221

In Maven2 muss ich Folgendes tun, um eine einzelne transitive Abhängigkeit auszuschließen:

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

Das Problem bei diesem Ansatz ist, dass ich dies für jede transitive Abhängigkeit tun muss, die von beigetragen wird sample-artifactB.

Gibt es eine Möglichkeit, eine Art Platzhalter zu verwenden, um alle transitiven Abhängigkeiten auf einmal anstatt einzeln auszuschließen?

pbreault
quelle
Manchmal muss man eine neueste Version der Bibliothek verwenden, z. B. Spring 2.5.6, aber einige andere Abhängigkeiten enthalten ältere Versionen, z. B. struts2-spring-plugin (2.1.6) enthält Spring 2.5.3. In solchen Szenarien muss die Version ausgeschlossen oder überschrieben werden.
Vinod Singh
1
Benutze Ivy. Ich mache nur Spaß.
Jake Toronto

Antworten:

54

Für maven2 gibt es keine Möglichkeit, das zu tun, was Sie beschreiben. Für Maven 3 gibt es. Wenn Sie Maven 3 verwenden, sehen Sie bitte eine andere Antwort auf diese Frage

Für Maven 2 würde ich empfehlen, einen eigenen benutzerdefinierten POM für die Abhängigkeit zu erstellen, die Ihre <Ausschlüsse> enthält. Stellen Sie für Projekte, die diese Abhängigkeit verwenden müssen, die Abhängigkeit auf Ihr benutzerdefiniertes POM anstelle des typischen Artefakts ein. Dadurch können Sie zwar nicht unbedingt alle transitiven Abhängigkeiten mit einem einzigen <Ausschluss> ausschließen, aber Sie müssen Ihre Abhängigkeit nur einmal schreiben, und alle Ihre Projekte müssen keine unnötigen und langen Ausschlusslisten führen.

Whaley
quelle
12
Ich würde empfehlen, keinen eigenen Pom zu machen, um Ausschlüsse zu umgehen. Dies macht Ihren Build weitaus weniger portabel und verringert das Verständnis.
Brian Fox
1
Für den Fall, dass Sie nicht an akzeptierten Antworten vorbei schauen: jira.codehaus.org/browse/MNG-3832
Jakub Bochenski
@JakubBochenski Die Antwort, die ich gegeben habe, ist spezifisch für Maven 2, mit dem diese Frage markiert ist (zu dem Zeitpunkt, als ich diesen Kommentar schrieb). Ihr Link ist nur für Maven 3 relevant. Unabhängig davon habe ich meine Antwort bearbeitet, um einen Link zu der höher bewerteten Antwort zu erstellen.
Whaley
306

Was für mich funktioniert hat (möglicherweise eine neuere Funktion von Maven), ist lediglich das Platzieren von Platzhaltern im Ausschlusselement.

Ich habe ein Projekt mit mehreren Modulen, das ein "App" -Modul enthält, auf das in zwei WAR-Paketen verwiesen wird. Eines dieser WAR-gepackten Module benötigt wirklich nur die Domänenklassen (und ich habe sie noch nicht vom App-Modul getrennt). Ich fand das funktioniert:

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

Der Platzhalter sowohl für die Gruppen-ID als auch für die Artefakt-ID schließt alle Abhängigkeiten aus, die normalerweise mit dieser Abhängigkeit an das Modul weitergegeben werden.

Enricopulatzo
quelle
9
Die * Wildcard für Gruppe und Artifiact scheint in Maven 3
nkr1pt
22
Ich weiß nicht, wie Sie dies gefunden haben, da Maven 3 ausdrücklich vor der Verwendung von Sternchen warnt: [WARNUNG] 'dependencies.dependency.exclusions.exclusion.groupId' für <artifcat_id> mit dem Wert "*" nicht stimmen mit einem gültigen ID-Muster überein. [WARNUNG] Es wird dringend empfohlen, diese Probleme zu beheben, da sie die Stabilität Ihres Builds gefährden. [WARNUNG] Aus diesem Grund unterstützen zukünftige Maven-Versionen möglicherweise nicht mehr das Erstellen solcher fehlerhafter Projekte. Würde es Ihnen etwas ausmachen, Beweise dafür zu liefern, dass es unterstützt wird und verwendet werden kann? Andernfalls würde ich Ihren Kommentar als äußerst irreführend betrachten.
ᄀ ᄀ
7
Arbeitete wunderbar mit Maven 3.0.4. Dank viel !
Evgeny Goldin
1
maven 3.0.4 -> es hat bei mir nicht gut funktioniert. Das resultierende JAR ist sehr unterschiedlich, wenn ich Asterix verwende oder wenn ich alle direkten Abhängigkeiten explizit ausschließe. Es kann mit der Tatsache zu tun haben, dass ich Maven-Assembly-Plugin verwende, um ein Fettglas zu erstellen. In diesem Fall funktioniert die vorgeschlagene Sulotion nicht!
Gilad hoch
31
Diese Methode ist gültig. Sie haben die Warnung behoben, dass andere in Maven 3.2.1 berichten: Issues.apache.org/jira/browse/MNG-3832
Ryan
32

Eine Sache habe ich nützlich gefunden:

Wenn Sie die Abhängigkeit mit den Ausschlüssen im Abschnitt dependencyManagement des übergeordneten POM für Ihr Projekt oder in einem importierbaren POM für das Abhängigkeitsmanagement einfügen, müssen Sie den Ausschluss (oder die Version) nicht wiederholen.

Zum Beispiel, wenn Ihr übergeordnetes POM Folgendes hat:

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

Dann können die Module in Ihrem Projekt die Abhängigkeit einfach wie folgt deklarieren:

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

Das im übergeordneten POM gibt sowohl die Version als auch die Ausschlüsse an. Ich verwende diese Technik für fast alle unsere Projekte und sie eliminiert viele Wiederholungen.

Joshua Davis
quelle
23

Vor drei Jahren habe ich empfohlen, Version 99 nicht zu verwenden, aber jetzt habe ich einen besseren Weg gefunden, zumal Version 99 offline ist:

Verwenden Sie im übergeordneten POM Ihres Projekts das Maven-Enforcer-Plugin, um den Build fehlzuschlagen , wenn sich die unerwünschte Abhängigkeit in den Build einschleicht. Dies kann mithilfe der Regel für gesperrte Abhängigkeiten des Plugins erfolgen :

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

Wenn Sie dann über eine unerwünschte Abhängigkeit informiert werden, schließen Sie diese im <dependencyManagement>Abschnitt des übergeordneten POM aus :

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

Auf diese Weise wird die unerwünschte Abhängigkeit nicht versehentlich angezeigt (im Gegensatz zu einer, <exclusion>die leicht zu vergessen ist), sie ist auch während der Kompilierungszeit nicht verfügbar (im Gegensatz zum providedGültigkeitsbereich), es gibt keine falschen Abhängigkeiten (im Gegensatz zu Version 99) und es ' Ich arbeite ohne ein benutzerdefiniertes Repository (im Gegensatz zu Version 99). Dieser Ansatz funktioniert sogar basierend auf der Version, den Klassifizierern, dem Bereich oder einer ganzen Gruppen-ID des Artefakts. Weitere Informationen finden Sie in der Dokumentation .

Esko Luontola
quelle
Beachten Sie, dass zumindest unter Maven 3.1 das <configuration>beim Ausführen des Ziels über die Befehlszeile ignoriert wird und direkt unter verschoben werden muss <plugin>.
David Harkness
Ich habe gerade etwas gefunden, das wie ein böser Maven-Bug aussieht - Version 3.5.2. Ich habe ein Projekt mit Submodulen, bei dem ich eine Abhängigkeit im übergeordneten <dependencyManagement>Bereich ausschließe. Wenn Sie ein mvn dependency:treein diesem bestimmten Projekt ausführen, wird die Abhängigkeit überhaupt nicht ausgeschlossen. Aber alle Projekte, die diese Abhängigkeit importieren, werden den <exclusions>vom anderen Projekt übergeordneten Pom nicht berücksichtigen - der ausgeschlossene wird sich einschleichen !!! Ich musste <exclusions>direkt zu jedem Modul pom wechseln .
cbaldan vor
11

Ich verwende die folgende Problemumgehung: Anstatt zu versuchen, das Artefakt in allen geeigneten Abhängigkeiten auszuschließen, zeichne ich die Abhängigkeit auf oberster Ebene als "bereitgestellt". Um beispielsweise den Versand von xml-apis "welcher Version auch immer" zu vermeiden:

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

Derzeit gibt es keine Möglichkeit, mehr als eine transitive Abhängigkeit gleichzeitig auszuschließen. Auf der Maven JIRA-Site gibt es jedoch eine entsprechende Funktionsanforderung:

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

Peter
quelle
6

Hierfür gibt es eine Problemumgehung. Wenn Sie den Umfang einer Abhängigkeit auf Laufzeit festlegen , werden transitive Abhängigkeiten ausgeschlossen. Beachten Sie jedoch, dass Sie zusätzliche Verarbeitung hinzufügen müssen, wenn Sie die Laufzeitabhängigkeit packen möchten.

Um die Laufzeitabhängigkeit in ein beliebiges Paket aufzunehmen, können Sie das Kopierziel des Maven-Dependency-Plugins für ein bestimmtes Artefakt verwenden .

Reicher Verkäufer
quelle
1
Dies half mir, Probleme mit dem Android Dalvik-Compiler zu umgehen, der einige der zweistufigen transitiven Einschlüsse nicht verarbeiten konnte - aber ich musste <scope>provided</scope>stattdessen verwenden<scope>runtime</scope> .
Garret Wilson
6

Wenn Sie alle transitiven Abhängigkeiten von einem Abhängigkeitsartefakt ausschließen müssen, das Sie in eine Assembly aufnehmen möchten, können Sie dies im Deskriptor für das Assembly-Plugin angeben:

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

Wenn Sie unter Eclipse entwickeln, können Sie im Abhängigkeitsdiagramm des POM-Editors (erweiterte Registerkarten aktiviert) nach der Abhängigkeit suchen, die Sie von Ihrem Projekt ausschließen möchten, und dann:

Klicken Sie mit der rechten Maustaste darauf -> "Maven-Artefakt ausschließen ..." und Eclipse schließt den Ausschluss für Sie aus, ohne herausfinden zu müssen, mit welcher Abhängigkeit die Bibliothek verknüpft ist.

Tib
quelle
Beachten Sie, dass dies nur funktioniert, wenn Sie das m2eclipse-Plugin verwenden
Nicolas Mommaerts
2

Was ist Ihr Grund, alle transitiven Abhängigkeiten auszuschließen?

Wenn es ein bestimmtes Artefakt gibt (z. B. Commons-Logging), das Sie von jeder Abhängigkeit ausschließen müssen, kann der Ansatz Version 99 nicht vorhanden hilfreich sein.


Update 2012: Verwenden Sie diesen Ansatz nicht. Verwenden Sie das Maven-Enforcer-Plugin und Ausschlüsse . Version 99 erzeugt falsche Abhängigkeiten und das Repository von Version 99 ist offline (es gibt ähnliche Spiegel, aber Sie können sich nicht darauf verlassen, dass sie für immer online bleiben; es ist am besten, nur Maven Central zu verwenden).

Esko Luontola
quelle
1

In einem ähnlichen Problem wurde die gewünschte Abhängigkeit mit dem angegebenen Umfang deklariert. Bei diesem Ansatz werden die transitiven Abhängigkeiten abgerufen, aber NICHT in die Paketphase einbezogen, was Sie möchten. Ich mag diese Lösung auch in Bezug auf die Wartung, da für die Wartung kein Pom oder benutzerdefinierter Pom wie in der Whaley-Lösung erforderlich ist. Sie müssen nur die spezifische Abhängigkeit im Container angeben und fertig sein

nkr1pt
quelle
-2

Verwenden Sie den neuesten Maven in Ihrem Klassenpfad. Dadurch werden doppelte Artefakte entfernt und das neueste Maven-Artefakt beibehalten.

Samraj
quelle