Maven: tambahkan ketergantungan ke stoples dengan jalur relatif

232

Saya memiliki toples berpemilik yang ingin saya tambahkan ke pom saya sebagai ketergantungan.

Tapi saya tidak ingin menambahkannya ke repositori. Alasannya adalah bahwa saya ingin perintah pakar seperti mvn compile, dll, bekerja di luar kotak. (Tanpa menuntut dari pengembang untuk menambahkannya ke beberapa repositori sendiri).

Saya ingin tabung berada di lib pihak ke-3 dalam kontrol sumber, dan menautkannya dengan jalur relatif dari file pom.xml.

Bisakah ini dilakukan? Bagaimana?

flybywire
sumber

Jawaban:

343

Saya ingin tabung berada di lib pihak ke-3 dalam kontrol sumber, dan menautkannya dengan jalur relatif dari file pom.xml.

Jika Anda benar-benar ingin ini (mengerti, jika Anda tidak dapat menggunakan repositori perusahaan), maka saran saya akan menggunakan "file repositori" lokal untuk proyek dan untuk tidak menggunakan sebuah systemketergantungan scoped. The systemscoped harus dihindari, dependensi tersebut tidak bekerja dengan baik di banyak situasi (misalnya dalam perakitan), mereka menyebabkan lebih banyak masalah daripada manfaat.

Jadi, sebagai gantinya, deklarasikan repositori lokal ke proyek:

<repositories>
  <repository>
    <id>my-local-repo</id>
    <url>file://${project.basedir}/my-repo</url>
  </repository>
</repositories>

Instal lib pihak ketiga Anda di sana menggunakan install:install-filedengan localRepositoryPathparameter:

mvn install:install-file -Dfile=<path-to-file> -DgroupId=<myGroup> \ 
                         -DartifactId=<myArtifactId> -Dversion=<myVersion> \
                         -Dpackaging=<myPackaging> -DlocalRepositoryPath=<path>

Pembaruan: Tampaknya install:install-filemengabaikan localRepositoryPathsaat menggunakan versi 2.2 dari plugin. Namun, ini berfungsi dengan versi 2.3 dan yang lebih baru dari plugin. Jadi gunakan nama plugin yang memenuhi syarat untuk menentukan versi:

mvn org.apache.maven.plugins:maven-install-plugin:2.3.1:install-file \
                         -Dfile=<path-to-file> -DgroupId=<myGroup> \ 
                         -DartifactId=<myArtifactId> -Dversion=<myVersion> \
                         -Dpackaging=<myPackaging> -DlocalRepositoryPath=<path>

dokumentasi maven-install-plugin

Akhirnya, nyatakan seperti ketergantungan lainnya (tetapi tanpa systemcakupan):

<dependency>
  <groupId>your.group.id</groupId>
  <artifactId>3rdparty</artifactId>
  <version>X.Y.Z</version>
</dependency>

Ini adalah IMHO solusi yang lebih baik daripada menggunakan systemlingkup karena ketergantungan Anda akan diperlakukan seperti warga negara yang baik (misalnya akan dimasukkan dalam majelis dan sebagainya).

Sekarang, saya harus menyebutkan bahwa "cara yang tepat" untuk menghadapi situasi ini di lingkungan perusahaan (mungkin tidak demikian halnya di sini) adalah menggunakan repositori perusahaan.

Thivent Pascal
sumber
2
Ini adalah ide yang bagus, tetapi pada Maven 2.2.1, plugin instal tampaknya mengabaikan localRepositoryPath...
Jake
1
Mengapa mendeklarasikan repo lokal? Mengapa tidak biarkan saja masuk ke ~ / .m2 / dengan yang lainnya.
Leif Gruenwoldt
6
@ leif81 Karena itu, repo dan perpustakaan diperiksa ke dalam repositori SCM -> Siapa pun yang melakukan checkout sumber memiliki semua yang mereka butuhkan untuk membuat salinan perpustakaan / aplikasi.
Darth Android
6
Saya memiliki masalah yang sama dengan @lemon, yang saya perbaiki dengan melakukan basedir/./my-local-repodengan satu .saja.
Brian
2
Kemasan harus jar, oleh karena itu -Paket = jar
Danila Piatov
127

Menggunakan systemruang lingkup. ${basedir}adalah direktori pom Anda.

<dependency>
    <artifactId>..</artifactId>
    <groupId>..</groupId>
    <scope>system</scope>
    <systemPath>${basedir}/lib/dependency.jar</systemPath>
</dependency>

Namun disarankan agar Anda menginstal toples Anda di repositori, dan tidak mengikatnya ke SCM - setelah semua itulah yang coba dihilangkan oleh pakar.

Bozho
sumber
15
Sistem ruang lingkup harus dihindari dimanapun dimungkinkan. Instal JAR di repositori adalah solusi yang lebih baik ...
Gandalf StormCrow
14
ya, jika memungkinkan. dia mengatakan secara eksplisit bahwa dia tidak ingin memasukkannya ke dalam repositori. Saya menambahkan komentar untuk menunjukkan bahwa ini bukan praktik yang baik. Tapi itu berhasil.
Bozho
groovy, Anda solusi yang paling dapat diterima sejauh saya kira .. Aku benar-benar salah membaca pertanyaan
ant
Ya - pertanyaan itu sendiri tidak termasuk jawaban terbaik. Menempatkan segala sesuatu di server kontrol sumber tunggal tidak ada hubungannya dengan "membangun di luar kotak"; alih-alih, semuanya harus "dikontrol". Lakukan check-in pom's & settings.xml (menunjuk ke repo internal ), dan gunakan dua server untuk proyek Anda: (1) kontrol sumber, (2) kontrol artefak yang dihasilkan. Masuk akal tentang banyak memeriksa dalam stoples seperti halnya memeriksa dll (corp lama saya benar-benar melakukan check-in stoples & lib.a / .so / .dll's. Server p4 kami sangat lambat setelah itu, beberapa hg diam-diam digunakan untuk hari kerja sehari-hari - Masalah terpecahkan?
michael
cara apa pun untuk menentukan direktori yang berisi guci, jadi kita tidak harus menambahkan masing-masing dan setiap orang seperti halnya gradle dapat melakukannya?
Dean Hiller
29

Ini adalah metode lain selain jawaban saya sebelumnya di Bisakah saya menambahkan toples ke maven 2 membangun classpath tanpa menginstalnya?

Ini akan melewati batas ketika menggunakan multi-modul build terutama jika JAR yang diunduh dirujuk dalam proyek anak di luar induk. Ini juga mengurangi pekerjaan pengaturan dengan membuat file POM dan SHA1 sebagai bagian dari build. Ini juga memungkinkan file untuk berada di mana saja di proyek tanpa memperbaiki nama atau mengikuti struktur penyimpanan pakar.

Ini menggunakan maven-install-plugin. Agar ini berfungsi, Anda perlu mengatur proyek multi-modul dan memiliki proyek baru yang mewakili build untuk menginstal file ke dalam repositori lokal dan memastikan bahwa yang pertama.

Anda proyek multi-modul pom.xml akan terlihat seperti ini:

<packaging>pom</packaging>
<modules>
<!-- The repository module must be first in order to ensure
     that the local repository is populated -->
    <module>repository</module>
    <module>... other modules ...</module>
</modules>

File repositori / pom.xml kemudian akan berisi definisi untuk memuat JAR yang merupakan bagian dari proyek Anda. Berikut ini adalah beberapa cuplikan dari file pom.xml.

<artifactId>repository</artifactId>
<packaging>pom</packaging>

Kemasan pom mencegah hal ini dari melakukan tes atau mengkompilasi atau menghasilkan file jar. Daging pom.xml ada di bagian build tempat maven-install-plugin digunakan.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-install-plugin</artifactId>
            <executions>
                <execution>
                        <id>com.ibm.db2:db2jcc</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>install-file</goal>
                        </goals>
                        <configuration>
                            <groupId>com.ibm.db2</groupId>
                            <artifactId>db2jcc</artifactId>
                            <version>9.0.0</version>
                            <packaging>jar</packaging>
                            <file>${basedir}/src/jars/db2jcc.jar</file>
                            <createChecksum>true</createChecksum>
                            <generatePom>true</generatePom>
                        </configuration>
                </execution>
                <execution>...</execution>
            </executions>
        </plugin>
    </plugins>
</build>

Untuk menginstal lebih dari satu file, tambahkan saja eksekusi.

Archimedes Trajano
sumber
Ini adalah satu-satunya yang bekerja untuk proyek multi-modul saya. Pendekatan <repositori> lokal untuk alasan yang tidak diketahui tidak berhasil. Jadi terima kasih!
Lonzak
10

Ini bekerja untuk saya: Katakanlah saya memiliki ketergantungan ini

<dependency>
    <groupId>com.company.app</groupId>
    <artifactId>my-library</artifactId>
    <version>1.0</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/lib/my-library.jar</systemPath>
</dependency>

Kemudian, tambahkan jalur kelas untuk ketergantungan sistem Anda secara manual seperti ini

<Class-Path>libs/my-library-1.0.jar</Class-Path>

Konfigurasi penuh:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <archive>
            <manifestEntries>
                <Build-Jdk>${jdk.version}</Build-Jdk>
                <Implementation-Title>${project.name}</Implementation-Title>
                <Implementation-Version>${project.version}</Implementation-Version>
                <Specification-Title>${project.name} Library</Specification-Title>
                <Specification-Version>${project.version}</Specification-Version>
                <Class-Path>libs/my-library-1.0.jar</Class-Path>
            </manifestEntries>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>com.company.app.MainClass</mainClass>
                <classpathPrefix>libs/</classpathPrefix>
            </manifest>
        </archive>
    </configuration>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.5.1</version>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/libs/</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>
RufusSC2
sumber
9

Saya sebelumnya telah menulis tentang pola untuk melakukan ini.

Ini sangat mirip dengan solusi yang diusulkan oleh Pascal, meskipun ia memindahkan semua dependensi tersebut ke modul repositori khusus sehingga Anda tidak perlu mengulanginya di mana pun dependensi digunakan jika itu adalah multi-module build.

Brett Porter
sumber
6

Pada dasarnya, tambahkan ini ke pom.xml:

...

<repositories>
   <repository>
       <id>lib_id</id>
       <url>file://${project.basedir}/lib</url>
   </repository>
</repositories>

...

<dependencies>
  ...
  <dependency>
      <groupId>com.mylibrary</groupId>
      <artifactId>mylibraryname</artifactId>
      <version>1.0.0</version>
  </dependency>
  ...
</dependencies>
Fulgencio Jara
sumber
4

kami beralih ke gradle dan ini bekerja jauh lebih baik di gradle;). kita cukup tentukan folder yang bisa kita masukkan guci untuk situasi sementara seperti itu. Kami masih memiliki sebagian besar botol kami didefinisikan di bagian manajemen ketergantungan khas (yaitu sama dengan pakar). Ini hanyalah satu lagi ketergantungan yang kami definisikan.

jadi pada dasarnya sekarang kita bisa memasukkan toples yang kita inginkan ke dalam lib dir kita untuk pengujian sementara jika itu bukan repositori maven di suatu tempat.

Dean Hiller
sumber
1
Bisakah Anda memberi contoh bagaimana Anda melakukan ini?
Thomas
2

Satu tambahan kecil untuk solusi yang diposting oleh Pascal

Ketika saya mengikuti rute ini, saya mendapat kesalahan di maven saat memasang ojdbc jar.

[INFO] --- maven-install-plugin:2.5.1:install-file (default-cli) @ validator ---
[INFO] pom.xml not found in ojdbc14.jar

Setelah menambahkan -DpomFile, masalah teratasi.

$ mvn install:install-file -Dfile=./lib/ojdbc14.jar -DgroupId=ojdbc \
   -DartifactId=ojdbc -Dversion=14 -Dpackaging=jar -DlocalRepositoryPath=./repo \
   -DpomFile=~/.m2/repository/ojdbc/ojdbc/14/ojdbc-14.pom
hari ini
sumber
0

Anda dapat menggunakan eclipse untuk menghasilkan Jar yang dapat dijalankan: Ekspor / Jar yang dapat dijalankan

pengguna1942990
sumber
Tidak yakin itu menjawab pertanyaan. Dia sudah memiliki file sebagai toples.
Johannes Jander
Eclipse mendukung uberjar atau toples yang diarsir, jadi ini solusinya, tetapi tidak untuk pakar sihir
Alex Lehmann