Wyklucz wszystkie przechodnie zależności jednej zależności

220

W Maven2, aby wykluczyć jedną zależność przechodnią, muszę zrobić coś takiego:

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

Problem z tym podejściem polega na tym, że muszę to robić dla każdej zależności przechodniej wniesionej przez sample-artifactB.

Czy istnieje sposób użycia jakiegoś symbolu wieloznacznego, aby wykluczyć wszystkie zależności przechodnie na raz zamiast jeden po drugim?

pbreault
źródło
Czasami trzeba użyć najnowszej wersji biblioteki, powiedzmy Spring 2.5.6, ale niektóre inne zależności obejmują starszą wersję, np. Struts2-spring-plugin (2.1.6) zawiera Spring 2.5.3. W takich scenariuszach wymagane jest wyłączenie lub zastąpienie wersji.
Vinod Singh
1
Użyj Ivy. Żartuję.
Jake Toronto,

Odpowiedzi:

54

W przypadku maven2 nie ma sposobu na robienie tego, co opisujesz. Dla maven 3 jest. Jeśli używasz maven 3, zobacz inną odpowiedź na to pytanie

W przypadku maven 2 zaleciłbym utworzenie własnego niestandardowego pom dla zależności, która zawiera <wykluczenia>. W przypadku projektów, które muszą korzystać z tej zależności, ustaw zależność na niestandardową pompę zamiast na typowy artefakt. Chociaż niekoniecznie pozwala to na wykluczenie wszystkich zależności przechodnich za pomocą pojedynczego <wykluczenia>, pozwala tylko napisać swoją zależność tylko raz, a wszystkie projekty nie muszą utrzymywać niepotrzebnych i długich list wykluczeń.

wieloryb
źródło
12
Odradzam tworzenie własnego pomu w celu obejścia wyłączeń. To sprawia, że ​​twoja kompilacja jest znacznie mniej przenośna i zmniejsza zrozumienie.
Brian Fox
1
W przypadku, gdy nie spoglądasz w przeszłość, zaakceptowano odpowiedź: jira.codehaus.org/browse/MNG-3832
Jakub Bochenski
@JububBochenski odpowiedź, którą podałem, jest specyficzna dla maven 2, z którą to pytanie jest oznaczone (w momencie pisania tego komentarza). Twój link jest ważny tylko dla maven 3. Niezależnie od tego, edytowałem swoją odpowiedź, aby link do linku do bardziej wysoko ocenionej odpowiedzi.
whaley
305

To, co zadziałało dla mnie (może być nowsza funkcja Maven), to po prostu stosowanie symboli wieloznacznych w elemencie wykluczenia.

Mam projekt wielomodułowy, który zawiera moduł „aplikacji”, do którego odwołują się dwa moduły z pakietem WAR. Jeden z tych modułów z pakietami WAR tak naprawdę potrzebuje tylko klas domen (i nie oddzieliłem ich jeszcze od modułu aplikacji). Znalazłem to do pracy:

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

Symbol wieloznaczny zarówno dla groupId, jak i artefactId wyklucza wszystkie zależności, które normalnie byłyby propagowane do modułu przy użyciu tej zależności.

enricopulatzo
źródło
9
* Symbol wieloznaczny dla grupy i artifiaktu wydaje się działać w maven 3
nkr1pt
22
Nie wiem, jak udało ci się znaleźć to działające, ponieważ Maven 3 wyraźnie ostrzega przed użyciem gwiazdki: [OSTRZEŻENIE] 'dependencies.dependency.exclusion.exclusion.groupId' dla <artart_art> o wartości „*” nie dopasuj prawidłowy wzorzec identyfikatora. [OSTRZEŻENIE] Zaleca się naprawienie tych problemów, ponieważ zagrażają one stabilności twojej wersji. [OSTRZEŻENIE] Z tego powodu przyszłe wersje Maven mogą już nie obsługiwać tworzenia takich źle sformułowanych projektów. Czy mógłbyś podać jakieś dowody na to, że jest on obsługiwany i może być używany? W przeciwnym razie uważam twój komentarz za wyjątkowo mylący.
ᄂ ᄀ
7
Pięknie współpracował z Maven 3.0.4. Dzięki dużo !
Evgeny Goldin,
1
maven 3.0.4 -> nie działało to dla mnie dobrze. wynikowy jar jest bardzo różny, gdy używam asterix lub gdy wyraźnie wykluczam wszystkie bezpośrednie zależności. może to mieć związek z faktem, że używam wtyczki maven-a-plugin do stworzenia grubego słoika. w takim przypadku sugerowane pochłanianie nie działa!
gilad hoch
31
Ta metoda jest poprawna. Naprawiono ostrzeżenie, które inni zgłaszają w maven 3.2.1: Issues.apache.org/jira/browse/MNG-3832
Ryan
32

Jedna rzecz, którą uważam za przydatną:

Jeśli umieścisz zależność z wykluczeniami w sekcji dependenceManagement macierzystej POM dla swojego projektu lub w importowanej POM POM do zarządzania zależnościami, nie musisz powtarzać wykluczenia (ani wersji).

Na przykład, jeśli twoja nadrzędna POM ma:

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

Następnie moduły w projekcie mogą po prostu zadeklarować zależność jako:

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

W macierzystej POM określi zarówno wersję, jak i wykluczenia. Używam tej techniki do prawie wszystkich naszych projektów i eliminuje to wiele powtórzeń.

Joshua Davis
źródło
23

Trzy lata temu zalecałem używanie wersji 99 nie istnieje, ale teraz wymyśliłem lepszy sposób, zwłaszcza, że ​​wersja 99 jest offline:

W macierzystej POM projektu użyj wtyczki maven-enforcer-plug, aby zakończyć kompilację, jeśli niechciana zależność wkradnie się do kompilacji. Można to zrobić za pomocą reguły zakazanych zależności wtyczki :

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

Następnie, gdy ostrzeże Cię o niechcianej zależności, wyklucz ją w sekcji nadrzędnej POM <dependencyManagement>:

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

W ten sposób niechciana zależność nie pojawi się przypadkowo (w przeciwieństwie do tej, <exclusion>którą łatwo zapomnieć), nie będzie dostępna nawet podczas kompilacji (w przeciwieństwie do providedzakresu), nie ma fałszywych zależności (w przeciwieństwie do wersji 99) i „ Będę działać bez niestandardowego repozytorium (w przeciwieństwie do wersji 99). Takie podejście będzie działać nawet w oparciu o wersję artefaktu, klasyfikatory, zakres lub całą grupę ID - szczegółowe informacje można znaleźć w dokumentacji .

Esko Luontola
źródło
Zauważ, że przynajmniej w Maven 3.1, <configuration>jest on ignorowany podczas wykonywania celu z linii poleceń i musi zostać przeniesiony bezpośrednio pod <plugin>.
David Harkness,
Właśnie znalazłem coś, co wygląda jak paskudny błąd Maven - wersja 3.5.2. Mam projekt z podmodułami, w którym wykluczam zależność w sekcji rodzica <dependencyManagement>. Uruchomienie mvn dependency:treew tym konkretnym projekcie nie będzie miało żadnej wykluczonej zależności. Ale wszystkie projekty importujące tę zależność nie będą honorować <exclusions>drugiego projektu nadrzędnego pom - wykluczony wkradnie się !!! Musiałem przejść bezpośrednio <exclusions>do każdego modułu pom.
cbaldan
11

Korzystam z następującego obejścia: zamiast próbować wykluczyć artefakt we wszystkich odpowiednich zależnościach, rysuję zależność jako „pod warunkiem” na najwyższym poziomie. Na przykład, aby uniknąć wysyłania „dowolnej wersji” xml-apis:

    <dependency>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
        <version>[1.0,]</version>
        <scope>provided</scope>
    </dependency>
Michael Zilbermann
źródło
6

Istnieje obejście tego problemu, jeśli ustawisz zakres zależności na środowisko wykonawcze , zależności przechodnie zostaną wykluczone. Pamiętaj jednak, że oznacza to konieczność dodatkowego przetwarzania, jeśli chcesz spakować zależność środowiska wykonawczego.

Aby uwzględnić zależność środowiska wykonawczego w dowolnym opakowaniu, możesz użyć celu kopiowania wtyczki maven-zależności dla określonego artefaktu .

Bogaty sprzedawca
źródło
1
Pomogło mi to obejść problemy z kompilatorem Dalvik dla Androida, który nie był w stanie obsłużyć niektórych dwupoziomowych wtrąceń przechodnich --- ale musiałem użyć <scope>provided</scope>zamiast tego <scope>runtime</scope>.
Garret Wilson
6

jeśli chcesz wykluczyć wszystkie zależności przechodnie z artefaktu zależności, który zamierzasz dołączyć do zestawu, możesz to określić w deskryptorze wtyczki zestawu:

<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
źródło
3

Jeśli tworzysz w środowisku Eclipse, możesz w wykresie zależności Edytora POM (włączone karty zaawansowane) szukać zależności, którą chcesz wykluczyć z projektu, a następnie:

kliknij na niego prawym przyciskiem myszy -> „Wyklucz artefakt Maven ...”, a Eclipse zrobi dla ciebie wykluczenie bez potrzeby sprawdzania, z którą zależnością jest połączona biblioteka lib.

Tib
źródło
zwróć uwagę, że działa to tylko wtedy, gdy używasz wtyczki m2eclipse
Nicolas Mommaerts
2

Jaki jest powód wyłączenia wszystkich zależności przechodnich?

Jeśli istnieje konkretny artefakt (taki jak logowanie wspólne), który należy wykluczyć z każdej zależności, pomocne może być podejście w wersji 99 nie istnieje .


Aktualizacja 2012: nie używaj tego podejścia. Użyj wtyczki maven-enforcer i wykluczeń . Wersja 99 wytwarza fałszywe zależności, a repozytorium wersji 99 jest offline (istnieją podobne kopie lustrzane, ale nie można na nich polegać, aby pozostać online na zawsze; najlepiej używać tylko Maven Central).

Esko Luontola
źródło
1

W zagadnieniu podobnym zadeklarowałem pożądaną zależność z podanym zakresem. Przy takim podejściu przechodnie są pobierane, ale NIE są uwzględniane w fazie pakietu, co jest tym, czego chcesz. Podoba mi się również to rozwiązanie pod względem konserwacji, ponieważ nie ma pom lub niestandardowego pom, jak w rozwiązaniu whaley, wymaganego do utrzymania; wystarczy podać konkretną zależność w kontenerze i gotowe

nkr1pt
źródło
-2

Użyj najnowszego maven na swojej ścieżce klasy. Usunie to zduplikowane artefakty i zachowa najnowszy artefakt maven.

Samraj
źródło