Membangun toples yang dapat dieksekusi dengan maven?


122

Saya mencoba membuat jar yang dapat dieksekusi untuk proyek rumah kecil bernama "logmanager" menggunakan maven, seperti ini:

Bagaimana cara membuat JAR yang dapat dieksekusi dengan dependensi menggunakan Maven?

Saya menambahkan potongan yang ditampilkan di sana ke pom.xml, dan menjalankan mvn assembly: assembly. Ini menghasilkan dua file jar di logmanager / target: logmanager-0.1.0.jar, dan logmanager-0.1.0-jar-with-dependencies.jar. Saya mendapatkan pesan kesalahan ketika saya mengklik dua kali pada botol pertama:

Could not find the main class: com.gorkwobble.logmanager.LogManager. Program will exit.

Kesalahan yang sedikit berbeda ketika saya mengklik dua kali jar-with-dependencies.jar:

Failed to load Main-Class manifest attribute from: C:\EclipseProjects\logmanager\target\logmanager-0.1.0-jar-with-dependencies.jar

Saya menyalin dan menempelkan jalur dan nama kelas, dan memeriksa ejaan di POM. Kelas utama saya diluncurkan dengan baik dari konfigurasi peluncuran gerhana. Bisakah seseorang membantu saya mencari tahu mengapa file jar saya tidak bisa berjalan? Juga, mengapa ada dua botol untuk memulai? Beri tahu saya jika Anda memerlukan informasi lebih lanjut.

Berikut lengkapnya pom.xml, untuk referensi:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.gorkwobble</groupId>
  <artifactId>logmanager</artifactId>
  <name>LogManager</name>
  <version>0.1.0</version>
  <description>Systematically renames specified log files on a scheduled basis. Designed to help manage MUSHClient logging and prevent long, continuous log files.</description>
  <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.2</version>
            <!-- nothing here -->
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2-beta-4</version>
            <configuration>
              <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
              </descriptorRefs>
              <archive>
                <manifest>
                  <mainClass>com.gorkwobble.logmanager.LogManager</mainClass>
                </manifest>
              </archive>
            </configuration>
            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>single</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <source>1.6</source>
              <target>1.6</target>
            </configuration>
          </plugin>
    </plugins>
  </build>
  <dependencies>
    <!-- commons-lang -->
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.4</version>
    </dependency> 

    <!-- Quartz scheduler -->
    <dependency>
        <groupId>opensymphony</groupId>
        <artifactId>quartz</artifactId>
        <version>1.6.3</version>
    </dependency>
    <!-- Quartz 1.6.0 depends on commons collections -->
    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>3.1</version>
    </dependency>
    <!-- Quartz 1.6.0 depends on commons logging -->
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.1</version>
    </dependency>
    <!-- Quartz 1.6.0 requires JTA in non J2EE environments -->
    <dependency>
      <groupId>javax.transaction</groupId>
      <artifactId>jta</artifactId>
      <version>1.1</version>
      <scope>runtime</scope>
    </dependency>

    <!-- junitx test assertions -->
    <dependency>
        <groupId>junit-addons</groupId>
        <artifactId>junit-addons</artifactId>
        <version>1.4</version>
        <scope>test</scope>
    </dependency>

    <!-- junit dependency; FIXME: make this a separate POM -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.1</version>
    </dependency>

  </dependencies>
  <dependencyManagement>
  </dependencyManagement>
</project>

Jawaban:


244

Sebenarnya, saya pikir jawaban yang diberikan dalam pertanyaan yang Anda sebutkan salah ( UPDATE - 20101106: seseorang memperbaikinya, jawaban ini mengacu pada versi sebelum pengeditan ) dan ini menjelaskan, setidaknya sebagian, mengapa Anda mengalami masalah.


Ini menghasilkan dua file jar di logmanager / target: logmanager-0.1.0.jar, dan logmanager-0.1.0-jar-with-dependencies.jar.

Yang pertama adalah JAR modul logmanager yang dibuat selama packagefase oleh jar:jar(karena modul memiliki tipe pengemasan jar). Yang kedua adalah assembly yang dihasilkan oleh assembly:assemblydan harus berisi class dari modul saat ini dan dependensinya (jika Anda menggunakan deskriptor jar-with-dependencies).

Saya mendapatkan pesan kesalahan ketika saya mengklik dua kali pada botol pertama:

Could not find the main class: com.gorkwobble.logmanager.LogManager. Program will exit.

Jika Anda menerapkan konfigurasi yang disarankan dari tautan yang diposting sebagai referensi, Anda mengonfigurasi plugin jar untuk menghasilkan artefak yang dapat dieksekusi, seperti ini:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <mainClass>com.gorkwobble.logmanager.LogManager</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>

Jadi logmanager-0.1.0.jarmemang dapat dieksekusi tetapi 1. ini bukan yang Anda inginkan (karena tidak memiliki semua dependensi) dan 2. tidak mengandung com.gorkwobble.logmanager.LogManager(inilah yang dikatakan kesalahan, periksa konten toples).

Kesalahan yang sedikit berbeda ketika saya mengklik dua kali jar-with-dependencies.jar:

Failed to load Main-Class manifest attribute from: C:\EclipseProjects\logmanager\target\logmanager-0.1.0-jar-with-dependencies.jar

Sekali lagi, jika Anda mengonfigurasi plugin assembly seperti yang disarankan, Anda memiliki sesuatu seperti ini:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
    </configuration>
  </plugin>

Dengan penyiapan ini, logmanager-0.1.0-jar-with-dependencies.jarberisi kelas-kelas dari modul saat ini dan dependensinya tetapi, menurut kesalahannya, META-INF/MANIFEST.MF ini tidak berisi Main-Classentri (kemungkinan besar MANIFEST.MF tidak sama seperti di logmanager-0.1.0.jar). Stoples sebenarnya tidak dapat dieksekusi, yang sekali lagi bukan yang Anda inginkan.


Jadi, saran saya adalah menghapus configurationelemen dari maven-jar-plugin dan mengkonfigurasi maven-assembly-plugin seperti ini:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.2</version>
    <!-- nothing here -->
  </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.2-beta-4</version>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <archive>
        <manifest>
          <mainClass>org.sample.App</mainClass>
        </manifest>
      </archive>
    </configuration>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

Tentu saja, ganti org.sample.Appdengan kelas yang ingin Anda jalankan. Bonus kecil, saya sudah terikat assembly:singlepada packagefase jadi Anda tidak perlu lari assembly:assemblylagi. Jalankan saja mvn installdan perakitan akan diproduksi selama pembuatan standar.

Jadi, perbarui pom.xml Anda dengan konfigurasi yang diberikan di atas dan jalankan mvn clean install. Kemudian, cd ke targetdirektori dan coba lagi:

java -jar logmanager-0.1.0-jar-with-dependencies.jar

Jika Anda mendapatkan kesalahan, harap perbarui pertanyaan Anda dengannya dan posting konten META-INF/MANIFEST.MFfile dan bagian yang relevan dari Anda pom.xml(bagian konfigurasi plugin). Juga harap posting hasil dari:

java -cp logmanager-0.1.0-jar-with-dependencies.jar com.gorkwobble.logmanager.LogManager

untuk menunjukkan bahwa itu berfungsi dengan baik pada baris perintah (terlepas dari apa yang dikatakan gerhana).

EDIT: Untuk Java 6, Anda perlu mengkonfigurasi maven-compiler-plugin. Tambahkan ini ke pom.xml Anda:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
      <source>1.6</source>
      <target>1.6</target>
    </configuration>
  </plugin>

4
Terima kasih atas komentar Anda! Saya mengubah pom.xml saya seperti yang Anda tentukan. Ketika saya menjalankan mvn clean install, saya mendapatkan banyak kesalahan kompilasi dari kode saya, mengatakan bahwa anotasi dan sebagainya tidak didukung dalam -sumber 1.3. Saya menggunakan jdk1.6 dan mengkompilasi di eclipse; Saya tidak yakin bagaimana 1.3 diperkenalkan. Mungkin salah satu versi pustaka di potongan pom adalah yang lebih lama?
RMorrisey

Terima kasih! Saya berhasil melewati masalah 1.3. Saya juga harus menambahkan ketergantungan junit4 ke POM saya. Saya sedang memecahkan masalah lain; jika saya buntu, saya akan memposting lagi! Jika saya menjalankan stoples, saya akan menandai ini sebagai jawaban. POM saya saat ini diperbarui pada pertanyaan di atas.
RMorrisey

Apakah ada cara untuk mengecualikan sumber daya dari file jar yang dihasilkan?

2
Mungkinkah menghasilkan jar memiliki nama "normal"?
Daniil Shevelev

1
Saya juga menemukan entri blog Sonatype ini berguna

15

Jawaban Pascal Thivent membantu saya juga. Tetapi jika Anda mengelola plugin Anda di dalam <pluginManagement>elemen, Anda harus menentukan perakitan lagi di luar manajemen plugin, atau dependensi tidak dikemas dalam jar jika Anda menjalankan mvn install.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>


    <build>
        <pluginManagement>
            <plugins>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <source>1.6</source>
                        <target>1.6</target>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <version>2.4</version>
                    <configuration>
                        <archive>
                            <manifest>
                                <mainClass>main.App</mainClass>
                            </manifest>
                        </archive>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                    </configuration>
                    <executions>
                        <execution>
                            <id>make-assembly</id>
                            <phase>package</phase>
                            <goals>
                                <goal>single</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

            </plugins>

        </pluginManagement>

        <plugins> <!-- did NOT work without this  -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
            </plugin>
        </plugins>

    </build>


    <dependencies>
       <!--  dependencies commented out to shorten example -->
    </dependencies>

</project>

1
Terima kasih Mike, Ini membantu saya. Awalnya paket saya dibuat tanpa menggunakan <pluginManagement>. Tapi Eclipse memberikan beberapa kesalahan di pom.xml "maven - Eksekusi plugin tidak tercakup oleh siklus hidup". Yang mengganggu saya. Jadi untuk mengatasi ini saya menambahkan <pluginManagement>, sekarang kesalahan gerhana hilang tetapi paket saya berhenti dibuat. Cuplikan pom Anda di atas telah berhasil untuk saya. :)
shashaDenovo

2
Ini berguna .. saat menggunakan <pluginManagement>, jawaban teratas tidak akan berfungsi.
ininprsr

5

Jika Anda tidak ingin menjalankan tujuan perakitan pada paket, Anda dapat menggunakan perintah berikutnya:

mvn package assembly:single

Di sini paket adalah kata kunci.


-1

Klik kanan proyek dan berikan maven build, maven clean, maven generate resource dan maven install. File jar akan otomatis dibuat.

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.