23

When I run "clean and build" the .jar file that is being created only runs if the lib folder is at the same folder of the .jar file.

So if I move the jar file to the desktop and leave the lib folder in the dist folder, the jar file will give me an exception.

How can I deal with this problem?

Lucio
  • 4,753
  • 3
  • 48
  • 77
ksm001
  • 3,772
  • 10
  • 36
  • 57

12 Answers12

23

I solved this by creating just one jar file with all libraries inside, adding the following to my build.xml file in NetBeans:

<target name="-post-jar">
  <jar jarfile="dist/Combined-dist.jar">
    <zipfileset src="${dist.jar}" excludes="META-INF/*" />
    <zipfileset src="lib/commons-io-1.4.jar" excludes="META-INF/*" />
    <zipfileset src="lib/ninja-utils-3.2.jar" excludes="META-INF/*" />
    <zipfileset src="lib/unicorn-1.0.jar" excludes="META-INF/*" />
    <manifest>
        <attribute name="Main-Class" value="com.example.mypackage.Main"/>
    </manifest>
  </jar>
</target>

This creates a jar file (Combined-dist.jar) which is the combination of the dist jar and the specified library jars (in this case, commons-io-1.4.jar,ninja-utils-3.2.jar and unicorn-1.0.jar). You have to be sure to specify your Main Class package for the new jar file or it won't run when you try to open it.

Hemerson Varela
  • 24,034
  • 16
  • 68
  • 69
  • 1
    I added two jars to your example to help illustrate that you need to add one line for each jar you want to include. I know you can use a wildcard to add the entire lib directory, but I can't play with ant right now, so I'll post the simplest example (to avoid posting untested _code_). Thanks a lot for this answer! – jahroy Jun 20 '13 at 07:15
  • Just to note that it needs to be added just before the closing `` tag in `build.xml`. – István Ujj-Mészáros Oct 17 '13 at 00:09
  • What is it says the jar (for example you Combined-dist.jar) doesn't exists even I create it. I'm changing the package in too – diegoaguilar Oct 22 '13 at 13:54
  • Thank you bro. Saved a lot of time :) – GOBINATH.M Dec 18 '14 at 07:24
13

If you copy your jars into the source code directory, they will be in your final jar. Nevetheless, I am not sure if this will work 100% of the time.

There is a great post at java-forum that states the following:

Except for a select few circumstances, what works best for me is to simply merge the files manually. A .jar is basically a .zip with organized contents, and you can open them in almost any .zip capable archive program (I just use gnome's standard archiver, File Roller, and it works great). Backup your jar file and open it in the archiver of your choice, and do the same for each library jar in the library directory. Drag and drop the working folders (IE, everything EXCEPT the META-INF Directory) from each library into your jar's root path (alongside your META-INF and your app's root package). Now drag the META-INF/MANIFEST.MF file from your jar to your Desktop or any other folder. Open it, and erase the Class-Path and X-COMMENT lines. Don't forget to leave a blank newline at the end of the file! Save the new manifest file and drag it back to your jar's META-INF directory, overwriting the old one. Test the jar.

rlinden
  • 2,053
  • 1
  • 12
  • 13
9

That's really easy to package every dependent library (*.jar) into one single myProject.jar.

Just follow these steps and you will finally pack every dependent library into single jar. If you are using NetBeans then you can follow exactly or else you need to find your build.xml file in project files.

Follow these steps to edit build.xml

1) Click on Files tab on the left side of the project panel in NetBeans.

2) Double click on the build.xml file and add these lines in it just before </project> line

 <target name="package-for-store" depends="jar">
    <property name="store.jar.name" value="myProject"/>
    <property name="store.dir" value="store"/>
    <property name="store.jar" value="${store.dir}/${store.jar.name}.jar"/>
    <echo message="Packaging ${application.title} into a single JAR at ${store.jar}"/>
    <delete dir="${store.dir}"/>
    <mkdir dir="${store.dir}"/>
    <jar destfile="${store.dir}/temp_final.jar" filesetmanifest="skip">
        <zipgroupfileset dir="dist" includes="*.jar"/>
        <zipgroupfileset dir="dist/lib" includes="*.jar"/>
        <manifest>
            <attribute name="Main-Class" value="${main.class}"/>
        </manifest>
    </jar>
    <zip destfile="${store.jar}">
        <zipfileset src="${store.dir}/temp_final.jar"
        excludes="META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA"/>
    </zip>
    <delete file="${store.dir}/temp_final.jar"/>
</target>

3) Change value in second line of the code as per your project name which is

<property name="store.jar.name" value="myProject"/> //<---Just value not name

4) Save it and right click on build.xml and choose Run Target and then Other Targets and finally click on Package-for-store

5) And here you done. Now you can go and check just like dist folder there will be a store folder which will be containing your final complete jar including all of your dependent libraries. Now whenever you want to change / add more libraries or so, just follow step 4.

Picture for step 4

enter image description here

Airy
  • 5,484
  • 7
  • 53
  • 78
5

You could use Apache Ant since version 1.7 for build the JAR with the required libraries in only one file. You could have a configuration file as follows:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="buildJar">
    <target name="buildJar">
        <!-- Name of jar -->
        <jar destfile="C:/MyJar.jar" filesetmanifest="mergewithoutmain">
            <manifest>
                <!-- Your class with the main method -->
                <attribute name="Main-Class" value="myPackage.MyClass"/>
                <!-- Path in the jar -->
                <attribute name="Class-Path" value="."/>
            </manifest>
            <!-- Dir of compiled class -->
            <fileset dir="C:/NetBeansProjects/MyProject/bin"/>
            <!-- Include required jars -->
            <zipfileset excludes="META-INF/*.SF" 
                src="C:/NetBeansProjects/MyProject/lib/library1.jar"/>
            <zipfileset excludes="META-INF/*.SF" 
                src="C:/NetBeansProjects/MyProject/lib/library2.jar"/>
        </jar>
    </target>
</project>

In Netbeans, place the XML file in your project and run it with the context menu.

See more in Apache Ant User Manual.

Paul Vargas
  • 41,222
  • 15
  • 102
  • 148
3

If you are going to distribute your app to another pc

You just zip .jar along with lib folder.

If want to run your app from any place in your pc

Take in cosideration Maven way of doing this - create local repository eg. C:\libs where your libraries would exist and .jar could accesses them later from any place in your pc.

Or you could just use Maven. There is a discussion on distributing application with all dependencies (libraries): Java: How do I build standalone distributions of Maven-based projects?.

Community
  • 1
  • 1
d1e
  • 6,372
  • 2
  • 28
  • 41
3

Copy that jar file to:

C:\Program Files\Java\jdk\jre\lib\ext

and

C:\Program Files\Java\jre\lib\ext

You should be able to use it in Netbeans and in your manual imports, just like standard imports.

Ricardo Altamirano
  • 14,650
  • 21
  • 72
  • 105
2

I have found maybe the easiest solution for this problem here. You just need to copy the next code snippet at the end of the build.xml file in your project folder.

<target name="-post-jar">

    <!-- Change the value to the name of the final jar without .jar -->
    <property name="store.jar.name" value="MyJarName"/>

    <!-- don't edit below this line -->
    <property name="store.dir" value="dist"/>
    <property name="temp.dir" value="temp"/>
    <property name="store.jar" value="${store.dir}/${store.jar.name}.jar"/>

    <echo message="Packaging ${application.title} into a single JAR at ${store.jar}"/>

    <delete dir="${temp.dir}"/>
    <mkdir dir="${temp.dir}"/>

    <jar destfile="${temp.dir}/temp_final.jar" filesetmanifest="skip">
        <zipgroupfileset dir="dist" includes="*.jar"/>
        <zipgroupfileset dir="dist/lib" includes="*.jar"/>

        <manifest>
            <attribute name="Main-Class" value="${main.class}"/>
        </manifest>
    </jar>

    <delete dir="${store.dir}"/>

    <zip destfile="${store.jar}">
        <zipfileset src="${temp.dir}/temp_final.jar"
        excludes="META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA"/>
    </zip>

    <delete dir="${temp.dir}"/>

</target>
  1. Go to the build.xml in the root of your project and add the code right before </project> tag at the end.

  2. Now change the value of the first propertiy field as commented and save the changes.

  3. From now on, each time you Clean & Build your project, the full jar with dependencies will be generated in the project dist folder

DSantiagoBC
  • 464
  • 2
  • 11
Deniz Celebi
  • 888
  • 4
  • 14
  • 24
  • 1
    "I have developed"??? This was published 6 years earlier, with almost the same comments, by Robert Eckstein. http://www.oracle.com/technetwork/java/javamail/single-jar-141905.html – Mike Housky Mar 28 '17 at 13:39
  • @MikeHousky I edited the post to give credit to the original author. The edit was [rejected](http://stackoverflow.com/review/suggested-edits/15808434) because "This edit defaces the post in order to promote a product or service, or is deliberately destructive." I was perhaps misled by my time on outdoors.se, where [attribution is explicitly required](https://outdoors.meta.stackexchange.com/q/725/8887) for copied material. Here, it seems that attribution is not merely not required, but actively forbidden and regarded as "destructive" :(. – Pont May 01 '17 at 17:56
1

This is what worked for me:

I built in excel export functionality into my project. The 2 external .jars I used for this purpose was jxl.jar end sx.jar

Unpack these 2 jars into a folder(java classes) using 7-Zip without any META files. Unpack your project jar into the same folder including the META file.

Re-Pack the whole java classes folder using JARMaker to recreate your Project .jar in its original distribution folder ... and there you go ... full excel functionality.

Michael Celey
  • 12,645
  • 6
  • 57
  • 62
1

user1016588's solution works for me. There's one typo: this line should be zipfileset src="dist/lib/commons-io-1.4.jar" excludes="META-INF/*"

Gang Su
  • 1,187
  • 10
  • 12
1

Try this - in the Netbeans IDE:

  1. Go to Tools --> Libraries
  2. In the dialog box, on the bottom left click "New Library", give a name
  3. On the right side, click on "Add JAR/Folder"
  4. Click OK on the bottom right
  5. Re-start the IDE and check.
vfredrick
  • 71
  • 6
0

Follow these:- 1. Right click on project opened in netbeans editor 2. select properties 3. choose libraries 4. add jar 5. click ok

0

You can also use this (when the libraries are not in "dist/lib"), tested with NetBeans and ant-contrib:

 <target name="-post-jar">
  <taskdef resource="net/sf/antcontrib/antlib.xml">
    <classpath>
   <!-- Path to ant-contrib -->
   <pathelement location="../../Libs/ant-contrib-1.0b3.jar"/>
    </classpath>
  </taskdef>

  <!-- Change the value to the name of the final jar without .jar -->
  <property name="store.jar.name" value="${application.title}"/>

  <!-- don't edit below this line -->
  <property name="store.dir" value="dist"/>
  <property name="temp.dir" value="temp"/>
  <property name="temp.libs.dir" value="temp/libs"/>
  <property name="store.jar" value="${store.dir}/${store.jar.name}.jar"/>

  <echo message="Packaging ${application.title} into a single JAR at ${store.jar}"/>
  
  <fileset id="store.jars.absolute" dir="${store.dir}" includes="*.jar"/>  
  <pathconvert property="store.jars.relative" refid="store.jars.absolute" dirsep="/">
   <map from="${basedir}/" to=""/>
  </pathconvert>
  
  <for list="${store.jars.relative}" param="item">
   <sequential>
    <echo message="Adding @{item} into single JAR at ${store.jar}"/>
   </sequential>
  </for>

  <delete dir="${temp.dir}"/>
  <mkdir dir="${temp.dir}"/>
  
  <for list="${javac.classpath}" param="item" delimiter=":">
   <sequential>
    <echo message="Adding @{item} into single JAR at ${store.jar}"/>
    <copy file="@{item}" todir="${temp.libs.dir}" overwrite="true" />
   </sequential>
  </for>

  <jar destfile="${temp.dir}/temp_final.jar" filesetmanifest="skip">
   <zipgroupfileset dir="${store.dir}" includes="*.jar"/>
   <zipgroupfileset dir="${temp.libs.dir}" includes="*.*"/>

   <manifest>
    <attribute name="Main-Class" value="${main.class}"/>
   </manifest>
  </jar>

  <delete dir="${store.dir}"/>

  <zip destfile="${store.jar}">
   <zipfileset src="${temp.dir}/temp_final.jar" excludes="META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA"/>
  </zip>

  <delete dir="${temp.dir}"/>

 </target>
5chw4hn
  • 341
  • 3
  • 5