मैं मावेन के साथ अंतिम जार फ़ाइल के अंदर एक लाइब्रेरी फ़ोल्डर में सभी आवश्यक JAR फाइलें कैसे डालूं?


104

मैं अपने स्टैंडअलोन एप्लिकेशन में मावेन का उपयोग कर रहा हूं, और मैं अपने जेएआर फ़ाइल में सभी निर्भरताओं को एक लाइब्रेरी फ़ोल्डर के अंदर पैकेज करना चाहता हूं, जैसा कि यहां दिए गए उत्तर में दिया गया है:

मैं मावेन का उपयोग कर निर्भरता के साथ एक निष्पादन योग्य जार कैसे बना सकता हूं?

मैं चाहता हूं कि मेरी अंतिम JAR फ़ाइल में लाइब्रेरी फ़ोल्डर है जिसमें JAR फ़ाइलों के रूप में निर्भरताएं हैं, न कि यह maven-shade-pluginकि क्या निर्भरताएँ फ़ोल्डर के रूप में निर्भर करती हैं जैसे कि .M2 फ़ोल्डर में मावेन पदानुक्रम।

ठीक है, वास्तव में वर्तमान कॉन्फ़िगरेशन वही करता है जो मैं चाहता हूं, लेकिन मुझे एप्लिकेशन चलाते समय JAR फ़ाइलों को लोड करने में समस्या हो रही है। मैं कक्षाएं लोड नहीं कर सकता।

यहाँ मेरा विन्यास है:

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

प्रोजेक्ट ग्रहण से ठीक चलता है, और JAR फाइलें मेरे अंतिम JAR फ़ाइल के अंदर लाइब्रेरी फ़ोल्डर में डाल दी जाती हैं, लेकिन जब मैं लक्ष्य फ़ोल्डर से अंतिम JAR फ़ाइल चलाता हूं, तो मुझे हमेशा मिलती है 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.

मैं इस अपवाद को कैसे ठीक कर सकता हूं?


1
जार को चलाने के लिए आप किस कमांड का उपयोग करते हैं? शायद आप मावेन निष्पादन प्लगइन पसंद कर सकते हैं?
एंड्रे बोरिसोव

क्या पोम फ़ाइल की तुलना में अपवाद संदेश पुराना है? ऐसा लगता है कि मुख्य वर्ग com.myapp.MainClassको खोजा जा रहा है, नहीं com.tastycafe.MainClass
डंकन जोन्स

@ डंकन जोन्स, कॉपी पेस्ट समस्या, मैंने प्रश्न संपादित किया
महमूद सालेह

3
ध्यान दें कि यदि आप जार के अंदर जार चाहते हैं, तो जावा में मानक क्लास लोडर उन्हें समझ नहीं सकते हैं।
थोरबजोरन रेव एंडरसन

कैसे एक मज़बूत फ़ोल्डर में मावेन निर्भरता को जगह बनाने के लिए, लेकिन जार के बाहर?
ed22

जवाबों:


81

निम्नलिखित मेरा समाधान है। इसका परीक्षण करें यदि यह आपके लिए काम करता है:

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

पहला प्लग इन सभी निर्भरियों को टार्गेट / क्लासेस / लिबास फोल्डर में रखता है, और दूसरा अंतिम JAR फाइल में लाइब्रेरी फोल्डर को शामिल करता है, और Manifest.mfफाइल को कॉन्फ़िगर करता है।

लेकिन तब आपको JAR फ़ाइलों को लोड करने के लिए कस्टम क्लासलोडिंग कोड जोड़ना होगा।

या, कस्टम क्लासलोडिंग से बचने के लिए, आप "$ {project.build.directory} / lib का उपयोग कर सकते हैं, लेकिन इस मामले में, आपके पास अंतिम JAR फ़ाइल के अंदर निर्भरता नहीं है, जो उद्देश्य को हरा देती है।

यह सवाल पूछे जाने के बाद से दो साल हो गए हैं। नेस्टेड JAR फ़ाइलों की समस्या अभी भी बनी हुई है। मुझे उम्मीद है कि यह किसी की मदद करता है।


1
उपयोग: mvan स्थापित, सीडी लक्ष्य, जावा -जर MyJarFile-1.0.jar
djb

मुझे क्या याद है? यह एक प्रकट क्लासपैथ प्रविष्टि बनाता है जिसमें "lib /" होता है और सभी एक जार लिबर फ़ोल्डर से होता है। क्या यह इरादा है? क्यों?
अंतराल संशोधन

2
यह काम करने के बाद मैंने "$ {project.build.directory} / classes / lib" को $ {project.build.directory} / lib में बदल दिया
राजेंद्र थोराट

1
Unfortunatelly में प्रदान की गई निर्भरताएं शामिल हैं।
फिलिप जियोसेफी

@ राजेंद्र का धन्यवाद, इससे मदद मिली: $ {project.build.directory} / lib
मिंडुगास के।

30

अपडेट किया गया:

<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
यह लिबर फोल्डर को जार के बाहर रखता है (जो मुझे नहीं चाहिए)। क्या जार के अंदर काम डालने से बेहतर है? और इस मामले में ग्राहक को आवेदन कैसे वितरित करें?
महमूद सालेह 13

यह अब मेरे लिए अधिक स्पष्ट है। मुझे एक Google खोज करने दो। लेकिन मैं जानना चाहूंगा कि आप निष्पादन योग्य जार फ़ाइल के अंदर निर्दिष्ट फ़ोल्डर में सभी निर्भरता जार फ़ाइल को कॉपी क्यों करना चाहते हैं। यदि सभी निर्भरता जार फाइलें जार फ़ाइल के अंदर हैं, तो आपको उन्हें एक लेबर फ़ोल्डर में खोजने की आवश्यकता क्यों है?
अहमत कारकाया

23

सबसे सरल और सबसे कुशल तरीका इस तरह के एक uber प्लगइन का उपयोग करना है:

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

आप सभी को एक JAR फ़ाइल में डी-सामान्यीकृत करेंगे।


मेरे वर्तमान विन्यास के अतिरिक्त इसका उपयोग करें? और यह प्लगइन वास्तव में क्या करता है?
महमूद सालेह

15
मैं नहीं चाहता कि मेरी जार फ़ाइल इस तरह दिखे, मैं चाहता हूँ कि जार फ़ाइल के अंदर एक लिबर फ़ोल्डर में सभी निर्भरताएँ हों जैसे नेटबिन करता है।
महमूद सालेह

12

निष्पादन पैकर Maven प्लगइन वास्तव में उस उद्देश्य के लिए इस्तेमाल किया जा सकता: स्टैंडअलोन जावा किसी विशिष्ट फ़ोल्डर में जार फ़ाइलों के रूप में सभी निर्भरता युक्त अनुप्रयोग बनाने।

बस अपने सेक्शन के pom.xmlअंदर निम्नलिखित जोड़ें <build><plugins>( mainClassतदनुसार मूल्य बदलने के लिए सुनिश्चित करें ):

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

target/<YourProjectAndVersion>-pkg.jarआपके द्वारा चलाए जाने के बाद निर्मित JAR फ़ाइल स्थित है mvn package। इसके सभी संकलन-समय और रनटाइम निर्भरता को lib/JAR फ़ाइल के अंदर फ़ोल्डर में शामिल किया जाएगा ।

अस्वीकरण: मैं प्लगइन का लेखक हूं।


मैंने इसे आज़माया और मैं कह सकता हूं कि यह काम कर रहा है ... जैसा कि आपने कहा, यह प्लगइन एक जार फ़ाइल बनाता है, इसके पुस्तकालयों (जार) के साथ जार में एक कार्यशील निर्देशिका में ... कॉन्फ़िगरेशन वास्तव में आसान है .. मुझे लगता है कि यह क्या है इस सवाल के लेखक उम्मीद कर रहे हैं ... मैं आपको अपना वोट दूंगा ... इस पर एकमात्र दोष मुझे मिला है (यही कारण है कि मैं इसका इस्तेमाल नहीं कर सका), जब मैं अपना काम करता हूं तो देरी होती है जार और एप्लिकेशन को दिखाया गया है (लगभग 20 सेकंड) शायद कस्टम क्लासलोडर में लिबास को पंजीकृत करने की प्रक्रिया के कारण ... लेकिन यह एक महान दृष्टिकोण और एक उत्कृष्ट प्लगइन है ...
एडम एम। गंबा जी।

5

इस लिंक का अनुसरण:

कैसे करें: ग्रहण मावेन निर्भरता के साथ बिल्ड जार स्थापित करें

मुझे पता चला कि यह काम करने योग्य समाधान नहीं है क्योंकि क्लास लोडर जार के भीतर से जार लोड नहीं करता है, इसलिए मुझे लगता है कि मैं जार के अंदर निर्भरता को अनपैक कर दूंगा।


3

यहाँ है कि मैं यह कैसे करूँ:

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

और फिर मैं बस चलाता हूं:

mvn assembly:assembly

1
ध्यान दें कि आपको हमेशा हाथ से पहले एक संकलन करना चाहिए क्योंकि assemblyJAR में "टारगेट / क्लासेस" में जो कुछ भी होगा, वह बस डाल दिया जाएगा। यह सुनिश्चित करेगा कि JAR में आपके द्वारा हाल ही में स्रोत कोड में किए गए परिवर्तन शामिल हैं। तो, आप की तरह कुछ करना चाहिए: mvn clean compile assembly:assembly
नाका

2

मुझे इस सवाल का जवाब मिला:

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

न केवल आपको एक परिवाद फ़ोल्डर में आश्रित परिवाद फाइलें मिलती हैं, आपको एक बिन डायरेक्टर भी मिलता है जिसमें यूनिक्स और डॉस एक्जीक्यूटेबल दोनों होते हैं।

निष्पादन योग्य अंततः जावा को एक -cp तर्क के साथ कहता है जो आपके सभी आश्रित कामों को भी सूचीबद्ध करता है।

पूरा बहुत लक्ष्य फ़ोल्डर के अंदर एक appasembly फ़ोल्डर में बैठता है। महाकाव्य।

============= मुझे पता है कि यह एक पुराना धागा है, लेकिन यह अभी भी खोज परिणामों पर उच्च आ रहा है, इसलिए मैंने सोचा कि यह मेरे साथ किसी की मदद कर सकता है।


1

यह स्पष्ट रूप से एक वर्गीय समस्या है। ध्यान रखें कि जब आप IDE के बाहर अपना प्रोग्राम चलाते हैं तो क्लासपैथ को थोड़ा बदलना होगा। ऐसा इसलिए है क्योंकि IDE आपकी परियोजना के रूट फ़ोल्डर के सापेक्ष अन्य JAR को लोड करता है, जबकि अंतिम JAR के मामले में यह आमतौर पर सच नहीं है।

इन स्थितियों में मुझे जो करना पसंद है, वह JAR को मैन्युअली बनाना है। मुझे अधिकतम 5 मिनट लगते हैं और यह हमेशा समस्या को हल करता है। मैं आपको यह करने का सुझाव नहीं देता। मावेन का उपयोग करने का एक तरीका खोजें, यही इसका उद्देश्य है।


@SoboLAN JAR का निर्माण मैन्युअल रूप से यहाँ एक समाधान नहीं है। मावेन का उपयोग करने का इरादा है, जो "मैनुअल" के बिल्कुल विपरीत है!
डंकन जोन्स

@ डंकनजोन आप पूरी तरह से सही हैं। मेरा सुझाव है कि वह इसे करने के लिए मावेन का उपयोग करता है। हालाँकि, मेरे पास इसका कोई अनुभव नहीं है और मुझे ठीक से पता नहीं है कि क्या उपाय सुझाया जाता है। मैंने इसे दर्शाने के लिए अपना उत्तर संपादित किया।
राडू मुरझिया
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.