Kecualikan semua dependensi transitif dari satu dependensi


221

Di Maven2, untuk mengecualikan ketergantungan transitif tunggal, saya harus melakukan sesuatu seperti ini:

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

Masalah dengan pendekatan ini adalah bahwa saya harus melakukan ini untuk setiap ketergantungan transitif yang disumbangkan oleh sample-artifactB.

Apakah ada cara untuk menggunakan semacam wildcard untuk mengecualikan semua dependensi transitif sekaligus bukan satu-per-satu?


Kadang-kadang orang perlu menggunakan versi terbaru dari perpustakaan mengatakan Spring 2.5.6 tetapi beberapa dependensi lainnya termasuk versi yang lebih lama misalnya struts2-spring-plugin (2.1.6) termasuk Spring 2.5.3. Dalam skenario seperti itu ada persyaratan untuk pengecualian atau menimpa versi.
Vinod Singh

1
Gunakan Ivy. Hanya bercanda.
Jake Toronto

Jawaban:


54

Untuk maven2 tidak ada cara untuk melakukan apa yang Anda gambarkan. Untuk pakar 3, ada. Jika Anda menggunakan maven 3, silakan lihat jawaban lain untuk pertanyaan ini

Untuk pakar 2 saya akan merekomendasikan membuat pom kustom Anda sendiri untuk dependensi yang memiliki <exclusions> Anda. Untuk proyek yang perlu menggunakan dependensi itu, atur dependensi ke pom kustom Anda alih-alih artefak yang khas. Meskipun itu tidak selalu memungkinkan Anda mengecualikan semua dependensi transitif dengan <exclusion> tunggal, itu memungkinkan Anda hanya perlu menulis ketergantungan Anda sekali dan semua proyek Anda tidak perlu menyimpan daftar pengecualian yang tidak perlu dan panjang.


12
Saya akan merekomendasikan untuk tidak membuat pom Anda sendiri untuk mengatasi pengecualian. Ini membuat bangunan Anda jauh lebih mudah dibawa-bawa dan mengurangi pemahaman.
Brian Fox

1
Jika Anda tidak melihat melewati masa lalu yang diterima: jira.codehaus.org/browse/MNG-3832
Jakub Bochenski

@JakubBochenski jawaban yang saya berikan khusus untuk maven 2, yang ditandai dengan pertanyaan ini (pada saat saya menulis komentar ini). Tautan Anda hanya relevan untuk pakar 3. Terlepas dari apa pun, saya telah mengedit jawaban saya untuk menautkan tautan ke jawaban yang lebih tinggi mutunya.
whaley

306

Apa yang berhasil bagi saya (mungkin fitur yang lebih baru dari Maven) hanyalah melakukan wildcard dalam elemen pengecualian.

Saya memiliki proyek multi-modul yang berisi modul "aplikasi" yang direferensikan dalam dua modul yang dikemas dengan WAR. Salah satu modul yang dikemas dalam WAR benar-benar hanya membutuhkan kelas domain (dan saya belum memisahkannya dari modul aplikasi). Saya menemukan ini berfungsi:

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

Wildcard pada groupId dan artifactId mengecualikan semua dependensi yang biasanya akan menyebar ke modul menggunakan dependensi ini.


9
* Wildcard untuk grup dan artifiact tampaknya berfungsi di maven 3
nkr1pt

22
Saya tidak tahu bagaimana Anda dapat menemukan ini berfungsi, karena Maven 3 secara eksplisit memperingatkan tentang penggunaan tanda bintang: [PERINGATAN] 'dependencies.dependency.exclusions.exclusion.gexclusion.groupId' untuk <artifcat_id> dengan nilai "*" tidak cocok dengan pola id yang valid. [PERINGATAN] Sangat disarankan untuk memperbaiki masalah ini karena mengancam stabilitas bangunan Anda. [PERINGATAN] Karena alasan ini, versi Maven yang akan datang mungkin tidak lagi mendukung pembangunan proyek yang cacat seperti itu. Maukah Anda memberikan beberapa bukti bahwa itu didukung dan dapat digunakan? Kalau tidak, saya akan menganggap komentar Anda sangat menyesatkan.
ᄂ ᄀ

7
Bekerja dengan indah dengan Maven 3.0.4. Terima kasih banyak !
Evgeny Goldin

1
pakar 3.0.4 -> itu tidak bekerja dengan baik untuk saya. jar yang dihasilkan sangat jauh berbeda ketika saya menggunakan asterix, atau ketika saya secara eksplisit mengecualikan semua dependensi langsung. mungkin ada hubungannya dengan fakta saya menggunakan maven-assembly-plugin untuk membuat guci lemak. dalam hal ini, ramuan yang disarankan tidak bekerja!
gilad hoch

31
Metode ini valid. Mereka memperbaiki peringatan bahwa orang lain melaporkan dalam pakar 3.2.1: issues.apache.org/jira/browse/MNG-3832
Ryan

32

Satu hal yang menurut saya bermanfaat:

Jika Anda meletakkan ketergantungan dengan pengecualian di bagian dependencyManagement dari POM induk untuk proyek Anda, atau di POM manajemen ketergantungan yang dapat diimpor, maka Anda tidak perlu mengulangi pengecualian (atau versi).

Misalnya, jika POM orang tua Anda memiliki:

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

Maka modul-modul dalam proyek Anda dapat dengan mudah mendeklarasikan dependensi sebagai:

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

POM induk akan menentukan versi dan pengecualian. Saya menggunakan teknik ini untuk hampir semua proyek kami dan menghilangkan banyak pengulangan.


23

Tiga tahun lalu saya merekomendasikan menggunakan Versi 99 Tidak Ada, tapi sekarang saya sudah menemukan cara yang lebih baik, terutama karena Versi 99 sedang offline:

Di POM induk proyek Anda, gunakan maven-penegak-plugin untuk gagal membangun jika ketergantungan yang tidak diinginkan merangkak ke dalam membangun. Ini dapat dilakukan dengan menggunakan aturan dependensi yang dilarang 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>

Kemudian ketika itu memberi tahu Anda tentang ketergantungan yang tidak diinginkan, kecualikan di bagian induk 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>

Dengan cara ini ketergantungan yang tidak diinginkan tidak akan muncul secara tidak sengaja (tidak seperti hanya <exclusion>yang mudah dilupakan), itu tidak akan tersedia bahkan selama waktu kompilasi (tidak seperti providedruang lingkup), tidak ada dependensi palsu (tidak seperti Versi 99) dan itu ' akan bekerja tanpa repositori khusus (tidak seperti Versi 99). Pendekatan ini bahkan akan bekerja berdasarkan versi artifact, pengklasifikasi, ruang lingkup atau seluruh kelompok - lihat dokumentasi untuk detailnya.


Perhatikan bahwa setidaknya di bawah Maven 3.1, <configuration>diabaikan ketika mengeksekusi tujuan dari command-line dan harus dipindahkan langsung ke bawah <plugin>.
David Harkness

Saya baru saja menemukan apa yang tampak seperti bug Maven jahat - versi 3.5.2. Saya punya proyek dengan submodula di mana saya mengecualikan ketergantungan di bagian induk <dependencyManagement>. Menjalankan mvn dependency:treedalam proyek spesifik itu tidak akan memiliki ketergantungan sama sekali. Tetapi semua proyek yang mengimpor ketergantungan itu tidak akan menghormati <exclusions>dari pom induk proyek lainnya - yang dikecualikan akan masuk !!! Saya harus pindah <exclusions>ke setiap modul pom secara langsung.
cbaldan

11

Saya menggunakan solusi berikut: alih-alih mencoba mengecualikan artefak di semua dependensi yang sesuai, saya menggambar dependensi sebagai "disediakan" di tingkat atas. Misalnya, untuk menghindari pengiriman xml-apis "versi apa pun":

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


6

Ada solusi untuk ini, jika Anda mengatur cakupan dependensi menjadi runtime , dependensi transitif akan dikecualikan. Meskipun sadar ini berarti Anda perlu menambahkan pemrosesan tambahan jika Anda ingin mengemas ketergantungan runtime.

Untuk menyertakan dependensi runtime dalam kemasan apa pun, Anda dapat menggunakan tujuan salin maven-dependency-plugin untuk artefak tertentu .


1
Ini membantu saya mengatasi masalah dengan kompiler Dalvik Android yang tidak dapat menangani beberapa inklusi transitif dua tingkat --- tetapi saya harus menggunakannya <scope>provided</scope>sebagai gantinya <scope>runtime</scope>.
Garret Wilson

6

jika Anda perlu mengecualikan semua dependensi transitif dari artefak dependensi yang akan Anda sertakan dalam sebuah rakitan, Anda dapat menentukan ini dalam deskripsi untuk plugin rakitan:

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

3

Jika Anda mengembangkan di bawah Eclipse, Anda bisa di grafik ketergantungan ketergantungan POM Editor (tab canggih diaktifkan) untuk mencari ketergantungan yang ingin Anda kecualikan dari proyek Anda dan kemudian:

klik kanan di atasnya -> "Kecualikan Artefak Maven ..." dan Eclipse akan membuat pengecualian untuk Anda tanpa perlu mencari tahu di mana ketergantungan lib terhubung.


perhatikan bahwa ini hanya berfungsi jika Anda menggunakan plugin m2eclipse
Nicolas Mommaerts

2

Apa alasan Anda mengecualikan semua dependensi transitif?

Jika ada artefak tertentu (seperti pembalakan bersama) yang perlu Anda kecualikan dari setiap ketergantungan, pendekatan Versi 99 Tidak Ada mungkin membantu.


Pembaruan 2012: Jangan gunakan pendekatan ini. Gunakan maven-penegak-plugin dan pengecualian . Versi 99 menghasilkan dependensi palsu dan repositori Versi 99 sedang offline (ada mirror serupa tetapi Anda tidak bisa bergantung padanya untuk tetap online selamanya; yang terbaik hanya menggunakan Maven Central).


1

Dalam masalah simular saya memiliki ketergantungan yang diinginkan dinyatakan dengan ruang lingkup yang disediakan. Dengan pendekatan ini dependensi transitif diambil tetapi TIDAK termasuk dalam fase paket, yang adalah apa yang Anda inginkan. Saya juga menyukai solusi ini dalam hal pemeliharaan, karena tidak ada pom, atau custom pom seperti pada solusi whaley, yang perlu dipertahankan; Anda hanya perlu memberikan ketergantungan khusus dalam wadah dan dilakukan


-2

Gunakan maven terbaru di classpath Anda .. Ini akan menghapus duplikat artefak dan menyimpan artefak maven terbaru ..

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.