Step 1: Get One-jar. Go to the One-jar download page on Source-Forge and download the "one-jar-ant-task-0.97.jar" file.
Step 2: Integrate this jar into Eclipse so that when running Ant, Ant has access to the one-jar Ant Task. If you don't do this, you may get and error like:
/eclipse/helloworkspace/HelloOneJar/build.xml:54: Problem: failed to create task or type one-jar
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any/ declarations have taken place.
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any
Move the jar to your Eclipse plugins folder. For me, that was in /eclipse/plugins. You can really put this anywhere you want, but it made sense for me to put it here as Eclipse stores a lot of jars it needs here.
In Eclipse, open preferences, drill down to Ant-->Runtime, highlight Ant Home Entries, and click "Add external JARs...". Find the one-jar JAR, and add it here.
Step 3: Create Ant build file. For demonstration and testing purposes, I created a tiny Java Project called HelloOneJar which contains a Hello class. All the Hello class does is log two messages using log4j. Here is a screenshot of the project structure and the Hello class:
build.properties
project.name=hello-onejar lib.dir=lib src.dir=src build.dir=build dist.dir=dist
build.xml
<?xml version="1.0"?> <project name="hello-onejar" default="onejar" basedir="."> <taskdef name="one-jar" classname="com.simontuffs.onejar.ant.OneJarTask" onerror="report" /> <property file="build.properties"/> <tstamp> <format property="timestamp" pattern="yyyy-MM-dd HH:mm:ss" /> </tstamp> <path id="classpath"> <fileset dir="${lib.dir}" /> </path> <target name="clean"> <echo>Cleaning the ${build.dir}</echo> <delete dir="${build.dir}"/> <delete dir="${dist.dir}"/> </target> <target name="init" depends="clean"> <echo>Creating the build directory</echo> <mkdir dir="${build.dir}"/> <mkdir dir="${dist.dir}"/> </target> <target name="compile" depends="init"> <echo>Compile the source files</echo> <javac srcdir="${src.dir}" destdir="${build.dir}" debug="on"> <classpath refid="classpath"/> </javac> </target> <target name="mainjar" depends="compile"> <jar jarfile="${dist.dir}/main.jar"> <manifest> <attribute name="Built-By" value="${user.name}"/> <attribute name="Build-Date" value="${timestamp}"/> <attribute name="Main-Class" value="com.hello.Hello"/> </manifest> <fileset dir="${build.dir}"> <include name="**/*.class"/> </fileset> </jar> </target> <target name="onejar" depends="mainjar"> <!-- Construct the One-JAR file --> <one-jar destfile="${dist.dir}/${project.name}.jar"> <main jar="${dist.dir}/main.jar"> </main> <lib> <fileset dir="${lib.dir}" /> </lib> </one-jar> </target> </project>The follwing parts are very important!
<taskdef name="one-jar" classname="com.simontuffs.onejar.ant.OneJarTask" onerror="report" />
without that line, the one-jar task is undefined. Remember to tell Ant where this class is in step 2!
<attribute name="Main-Class" value="com.hello.Hello"/>
without this in the manifest you may get an error like this when you run your jar:
Exception in thread "main" java.lang.Exception: hello-onejar.jar main class was not found (fix: add main/main.jar with a Main-Class manifest attribute, or specify -Done-jar.main.class=), or use One-Jar-Main-Class in the manifest
at com.simontuffs.onejar.Boot.run(Boot.java:327)
at com.simontuffs.onejar.Boot.main(Boot.java:168)
at com.simontuffs.onejar.Boot.run(Boot.java:327)
at com.simontuffs.onejar.Boot.main(Boot.java:168)
Step 4: Run the Ant build. In this example, I run the "onejar" task that I defined. This build file first creates a jar called main.jar that contains my application code. This jar has it's own manifest and could be ran separately. The onejar target wraps main.jar in hello-one-jar.jar and packages all the jar(s) in the lib folder inside. Both jars are created in the ./dist folder.
Step 5: Inspect the built jar. This is how I did this on my Mac. First I created a folder: /HelloOneJar and moved the hello-onejar.jar into it. Then, in terminal:
cd /HelloOneJar
jar -xvf hello-onejar.jar
Now the jar is unpacked and we can see what's in it. You can do the same for main.jar and verify that the manifest file was created correctly. jar -xvf hello-onejar.jar
Step 6: Run the jar and make sure it all works. This is how I did this on my Mac. First I created a folder: /HelloOneJar and moved the hello-onejar.jar into it. Then, in terminal:
cd /HelloOneJar/
java -jar hello-onejar.jar
java -jar hello-onejar.jar
The following output appeared in Terminal:
0 [main] INFO com.hello.Hello - Hello.
1 [main] INFO com.hello.Hello - Bye Bye.
1 [main] INFO com.hello.Hello - Bye Bye.
Exactly what I expected!
Piece of Cake!!
10 comments:
Thanks, work for me. Luiz (Brazil).
@Luiz THanks for letting me know. Glad it helped you!!
I tried running the script and ant reported the error that it could not find the lib folder. How do I solve this.
Thanks
Do you have a folder in your project called lib with jars in it? You'll need that if you have external jars that your project needs to compile and run. If there are no jar dependencies, you don't need any of the parts in the build.xml file referring to ${lib.dir}.
Thank u a tonne! You saved my day!
Helped me. Thanks a ton. Got it working in no time. Can you please let me know on where to include my log4.properties file in case I want to include it in your one-jar jar file.
I followed the steps as you said but still getting following error in eclipse indigo on Mac lion
BUILD FAILED
build.xml:119: Problem: failed to create task or type one-jar
Cause: The name is undefined.
Action: Check the spelling.
Action: Check that any custom tasks/types have been declared.
Action: Check that any / declarations have taken place.
@Sandeep What do you have on line 119 in your build.xml file? Did you put the on-jar jar on the classpath?
Thanks, your example allowed me to get over the final hurdle. Having to do the jar task and then do the one-jar task with the result of the jar task and which parts go to the jar file and which parts go to the one-jar file was not clear. Now I have a working one-jar file.
Is it possible to use one-jar with applet application? I've a jar that contains applet classes and these classes need to use some libraries which is in lib folder.
Post a Comment