Gerekli tüm JAR dosyalarını Maven ile son JAR dosyasının içindeki bir kitaplık klasörüne nasıl koyabilirim?


105

Bağımsız uygulamamda Maven kullanıyorum ve JAR dosyamdaki tüm bağımlılıkları, buradaki cevaplardan birinde belirtildiği gibi bir kütüphane klasöründe paketlemek istiyorum:

Maven kullanarak bağımlılıkları olan çalıştırılabilir bir JAR'ı nasıl oluşturabilirim?

Son JAR maven-shade-plugindosyamın, bağımlılıkları .m2 klasörüne Maven hiyerarşisi gibi klasörler biçiminde koyduğu gibi değil, JAR dosyaları olarak bağımlılıkları içeren bir kitaplık klasörüne sahip olmasını istiyorum.

Aslında mevcut yapılandırma istediğimi yapıyor, ancak uygulamayı çalıştırırken JAR dosyalarını yüklemeyle ilgili bir sorun yaşıyorum. Dersleri yükleyemiyorum.

Yapılandırmam şöyle:

<plugins>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
            <execution>
                <id>copy-dependencies</id>
                <phase>prepare-package</phase>
                <goals>
                    <goal>copy-dependencies</goal>
                </goals>
                <configuration>
                    <outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
                    <overWriteReleases>false</overWriteReleases>
                    <overWriteSnapshots>false</overWriteSnapshots>
                    <overWriteIfNewer>true</overWriteIfNewer>
                </configuration>
            </execution>
        </executions>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
            <archive>
                <manifest>
                    <addClasspath>true</addClasspath>
                    <classpathPrefix>lib/</classpathPrefix>
                    <mainClass>com.myapp.MainClass</mainClass>
                </manifest>
            </archive>
        </configuration>
    </plugin>

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

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
            <execution>
                <id>install</id>
                <phase>install</phase>
                <goals>
                    <goal>sources</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.5</version>
        <configuration>
            <encoding>UTF-8</encoding>
        </configuration>
    </plugin>

</plugins>

Proje Eclipse'den sorunsuz çalışıyor ve JAR dosyaları istediğim gibi son JAR dosyamın içindeki kitaplık klasörüne yerleştiriliyor, ancak son JAR dosyasını hedef klasörden çalıştırırken her zaman şunu elde ediyorum ClassNotFoundException:

Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext
Caused by: java.lang.ClassNotFoundException: org.springframework.context.ApplicationContext
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: com.myapp.MainClass. Program will exit.

Bu istisnayı nasıl düzeltebilirim?


1
kavanozu çalıştırmak için hangi komutu kullanıyorsunuz? muhtemelen maven exec eklentisini tercih edebilirsiniz?
Andrey Borisov

İstisna mesajı, POM dosyasıyla karşılaştırıldığında güncel değil mi? Görünüşe göre ana sınıf com.myapp.MainClassaranıyor, değil com.tastycafe.MainClass.
Duncan Jones

@Duncan Jones, kopyala yapıştır sorunu, soruyu düzenledim
Mahmoud Saleh

3
Kavanozun içinde kavanoz istiyorsanız, Java'daki standart sınıf yükleyicilerin bunları anlayamayacağını unutmayın.
Thorbjørn Ravn Andersen

Maven bağımlılıklarını bir lib klasörüne ancak JAR'ın dışına nasıl yerleştirebilirim?
ed22

Yanıtlar:


82

Aşağıdaki benim çözümüm. Sizin için çalışıp çalışmadığını test edin:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
                <overWriteReleases>false</overWriteReleases>
                <overWriteSnapshots>false</overWriteSnapshots>
                <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
        </execution>
    </executions>
</plugin>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <!-- <classpathPrefix>lib</classpathPrefix> -->
                <!-- <mainClass>test.org.Cliente</mainClass> -->
            </manifest>
            <manifestEntries>
                <Class-Path>lib/</Class-Path>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

İlk eklenti tüm bağımlılıkları target / classes / lib klasörüne koyar ve ikincisi, son JAR dosyasındaki kitaplık klasörünü içerir ve dosyayı yapılandırır Manifest.mf.

Ancak, JAR dosyalarını yüklemek için özel sınıf yükleme kodu eklemeniz gerekecektir.

Veya, özel sınıf yüklemesini önlemek için "$ {project.build.directory} / lib" kullanabilirsiniz, ancak bu durumda, nihai JAR dosyası içinde amacı bozan bağımlılıklarınız yoktur.

Soru sorulalı iki yıl oldu. Yuvalanmış JAR dosyaları sorunu yine de devam etmektedir. Umarım birine yardımcı olur.


1
Kullanım: mvn install, cd target, java -jar MyJarFile-1.0.jar
djb

neyi özlüyorum Bu, "lib /" ve lib klasöründeki tüm tek jar içeren bir manifest sınıf yolu girişi oluşturur. Bu kasıtlı mı? Neden?
gapvision

2
"$ {Project.build.directory} / classes / lib" öğesini $ {project.build.directory} / lib olarak değiştirdikten sonra çalıştı
Rajendra Thorat

1
Ne yazık ki, sağlandığı şekilde beyan edilen bağımlılıkları içerir.
Philippe Gioseffi

@Rajendra teşekkürler, yardımcı oldu: $ {project.build.directory} / lib
Mindaugas K.

31

Güncellenmiş:

<build> 
  <plugins> 
    <plugin> 
    <artifactId>maven-dependency-plugin</artifactId> 
    <executions> 
      <execution> 
        <phase>install</phase> 
          <goals> 
            <goal>copy-dependencies</goal> 
          </goals> 
          <configuration> 
             <outputDirectory>${project.build.directory}/lib</outputDirectory> 
          </configuration> 
        </execution> 
      </executions> 
    </plugin> 
  </plugins> 
</build> 

4
bu, lib klasörünü jar'ın dışına koyar (istediğim şey bu değil). kütüphaneyi kavanozun içine koymaktan daha mı iyi? ve bu durumda uygulama müşteriye nasıl teslim edilir?
Mahmoud Saleh

benim için artık daha net. bir google araması yapmama izin verin. Ancak neden tüm bağımlılık jar dosyasını çalıştırılabilir jar dosyasının içindeki belirtilen klasöre kopyalamak istediğinizi bilmek istiyorum. Tüm bağımlılık jar dosyaları jar dosyasının içindeyse, bunları neden bir lib klasöründe bulmanız gerekiyor?
Ahmet Karakaya

23

En basit ve en verimli yol, bunun gibi bir uber eklentisi kullanmaktır:

          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <finalName>uber-${artifactId}-${version}</finalName>
            </configuration>
        </plugin>

Hepsi tek bir JAR dosyasında normalleştirilmiş olmayacak.


mevcut yapılandırmama ek olarak kullanabilir miyim? ve bu eklenti tam olarak ne yapıyor?
Mahmud Saleh

15
jar dosyamın böyle görünmesini istemiyorum, netbean'ın yaptığı gibi jar dosyasının içindeki bir lib klasöründeki tüm bağımlılıklara sahip olmak istiyorum.
Mahmoud Saleh

12

Yürütülebilir Packer maven eklentisi tam olarak bu amaç için kullanılabilir: belirli bir klasörde JAR dosyaları gibi tüm bağımlılıkları bulunduğu bağımsız java uygulamaları oluşturmak.

Aşağıdakileri bölümün pom.xmliçine eklemeniz <build><plugins>yeterlidir (değerini mainClassuygun şekilde değiştirdiğinizden emin olun ):

<plugin>
    <groupId>de.ntcomputer</groupId>
    <artifactId>executable-packer-maven-plugin</artifactId>
    <version>1.0.1</version>
    <configuration>
        <mainClass>com.example.MyMainClass</mainClass>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>pack-executable-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Oluşturulan JAR dosyası, target/<YourProjectAndVersion>-pkg.jarçalıştırdıktan sonra adresinde bulunur mvn package. Tüm derleme zamanı ve çalışma zamanı bağımlılıkları lib/, JAR dosyası içindeki klasöre dahil edilecektir .

Feragatname: Eklentinin yazarıyım.


Denedim ve çalıştığını söyleyebilirim ... Dediğin gibi bu eklenti, kütüphaneleri (kavanozları) ile kavanozdaki bir lib dizinine bir jar dosyası oluşturuyor ... Yapılandırma gerçekten çok kolay .. Sanırım ne bu sorunun yazarı bekliyor ... Size oyumu vereceğim ... Bulduğum tek dezavantaj (bu yüzden kullanamadım), jar ve uygulama gösteriliyor (yaklaşık 20 saniye) muhtemelen kütüphaneleri özel sınıf yükleyiciye kaydetme işlemi nedeniyle ... Ama bu harika bir yaklaşım ve mükemmel bir eklenti ...
Adam M. Gamboa G.


3

İşte bunu nasıl yapıyorum:

    <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <appendAssemblyId>false</appendAssemblyId>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <archive>
                    <manifest>
                        <mainClass>com.project.MainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

Ve sonra koşuyorum:

mvn assembly:assembly

1
Her zaman elden önce bir derleme yapmanız gerektiğine dikkat edin, çünkü assemblyJAR'daki "hedef / sınıflar" içindeki her şeyi koyacaktır. Bu, JAR'ın kaynak kodda yakın zamanda yaptığınız değişiklikleri içermesini sağlayacaktır. Yani, böyle bir şey yapmak gerekir: mvn clean compile assembly:assembly.
naXa

2

Sorunun cevabını buldum:

http://padcom13.blogspot.co.uk/2011/10/creating-standalone-applications-with.html

Bir lib klasöründeki bağımlı kitaplık dosyalarını almakla kalmaz, aynı zamanda hem bir unix hem de dos çalıştırılabilir bir bin direktörü elde edersiniz.

Yürütülebilir dosya nihayetinde tüm bağımlı kütüphanelerinizi de listeleyen bir -cp argümanıyla java'yı çağırır.

Tüm parti, hedef klasörün içindeki bir uygulama klasöründe bulunur. Epik.

============= Evet, bunun eski bir ileti dizisi olduğunu biliyorum, ancak hala arama sonuçlarında üst sıralarda yer alıyor, bu yüzden benim gibi birine yardımcı olabileceğini düşündüm.


1

Bu açıkça bir sınıf yolu problemidir. Programınızı IDE dışında çalıştırdığınızda sınıf yolunun biraz değişmesi gerektiğini dikkate alın. Bunun nedeni, IDE'nin diğer JAR'ları projenizin kök klasörüne göre yüklemesidir, ancak son JAR durumunda bu genellikle doğru değildir.

Bu durumlarda yapmaktan hoşlandığım şey JAR'ı manuel olarak oluşturmaktır. En fazla 5 dakikamı alıyor ve her zaman sorunu çözüyor. Bunu yapmanızı önermiyorum. Maven'i kullanmanın bir yolunu bulun, amacı bu.


@SoboLAN JAR'ı manuel olarak oluşturmak burada bir çözüm değildir. Amaç, "manuel" in tam tersi olan Maven'i kullanmaktır!
Duncan Jones

@DuncanJones Kesinlikle haklısınız. Bunu yapmak için Maven'i kullanmasını öneririm. Ancak, bununla ilgili hiçbir deneyimim yok ve tam olarak hangi çözümü önereceğimi bilmiyordum. Cevabımı bunu yansıtacak şekilde düzenledim.
Radu Murzea
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.