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?

mengacau
sumber
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.

ikan paus
sumber
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.

enricopulatzo
sumber
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.

Joshua Davis
sumber
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.

Esko Luontola
sumber
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>
Michael Zilbermann
sumber
9

Saat ini, tidak ada cara untuk mengecualikan lebih dari satu ketergantungan transitif pada suatu waktu, tetapi ada permintaan fitur untuk ini di situs Maven JIRA:

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

Peter
sumber
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 .

Penjual Kaya
sumber
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>
Superole
sumber
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.

Tib
sumber
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).

Esko Luontola
sumber
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

nkr1pt
sumber
-2

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

Samraj
sumber