Jar : No Class Def Found Error - java

I am trying to build a project using Ant Build and i have referenced several jars to make it work. Now When i put the jar created by Ant build in some other machine and run it.
I am getting the error saying NoClassDefFoundError org/apache... Not found.
Is there anyway to put all the referenced jars in the classpath of the project or in the manifest file?
Or is there anyway to repackage all the jar in a project?
I know there is one method using jarjar but I don't have any idea of how to use it.
Please suggest me some ideas, I've been stuck with this small problem for a long time.

When building with ANT the external jars you need are being added to the classpath by the ANT tool. Look in your build script, you most likely have an entry either in the javac task or in a setup task that defines your classpath.
After you build your code, your jar file only has your classes in it, the classes in the 3rd party jar files (like Apache) are not added to your jar file by default.
What you need to decide is do you want a single jar file with all needed classes or are you willing to deploy multiple jar files? If you're comfortable delivering your application as multiple jar files, you will want to provide a batch file or shell script to launch the application for the user that builds the classpath to include the deployed jars.
If you want one jar file, you can do something like below. Assume that all the 3rd party jars you have are in a directory identified by the ANT property lib.dir:
<jar destfile='${build.dir}/lib-jars.jar'>
<zipgroupfileset dir="${lib.dir}">
<include name="**/*.jar" />
</zipgroupfileset>
</jar>
<sleep seconds='1'/> <!-- avoid timestamp warnings -->
what this will do is create in your build.dir directory a single jar file named lib-jars.jar that contains all the classes from all of the 3rd party jars. Understand that this will result in equivalent files (like MANIFEST.MF files) being overwritten if they exist in multiple jars and only the last one will be present.
Once you have this new all-libs jar, you can then jar up your application classes and the contents of this all-libs jar into one jar:
<jar destfile='${jar.file}' basedir='${classes.dir}'>
<!-- using zipfileset we can filter on entries in the one file -->
<zipfileset src='${build.dir}/lib-jars.jar'>
<exclude name="META-INF/MANIFEST.MF"/>
</zipfileset>
<manifest>
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Main-Class" value="${main.class}"/>
<section name="common">
<attribute name="Specification-Title" value="${project.title}"/>
<attribute name="Specification-Version" value="${release.version}"/>
<attribute name="Specification-Vendor" value="${vendor}"/>
<attribute name="Implementation-Title" value="${project.title}"/>
<attribute name="Implementation-Version" value="${release.version}"/>
<attribute name="Implementation-Vendor" value="${vendor}"/>
</section>
</manifest>
</jar>
notice that I exclude the MANIFEST.MF file from the all-libs jar and create my own. Then end result of this is a single jar file that includes all of the classes/property files/resources from all of the library jar files and your classes.

Related

ANT / ProGuard: Removing files from *within* 3rd party JAR before packing using zipgroupfileset

I'm creating some runnable JARs (desktop JavaFX applications).
I have a fileset of the 3rd party JARs I'm including:
<fileset id="shared_lib" dir="${aux.debian.lib.dir}">
<include name="commons-lang3-3.4.jar"/>
<include name="commons-io-2.4.jar"/>
...
</fileset>
And I then use zipgroupfileset to include those in the final runnable JAR:
<jar destfile="myapp.jar" filesetmanifest="mergewithoutmain">
<zipgroupfileset refid="shared_lib"/>
<manifest>
<attribute name="Main-Class" value="mypackage.myapp"/>
<attribute name="Class-Path" value="."/>
</manifest>
<fileset dir="./classes" />
</jar>
When I then run ProGuard I get the following warnings multiple times (as each of the zipped JARs contain a LICENSE.txt and NOTICE.txt):
[proguard] Warning: can't write resource [META-INF/LICENSE.txt] (Duplicate zip entry [myapp.jar:META-INF/LICENSE.txt])
[proguard] Warning: can't write resource [META-INF/NOTICE.txt] (Duplicate zip entry [myapp.jar:META-INF/NOTICE.txt])
I've tried the various exclude options when defining the fileset, but they only exclude files from the fileset, not from within the include JARs.
Is there away to simply filter what gets zipped as part of the zipgroupfileset? Perhaps in ProGuard?
This is only a minor annoyance, as everything works with the warnings, but it's annoying me that something that I have a feeling should be simple is eluding me.
You can add duplicate="preserve" to your <jar> element, as described in the documentation:
duplicate
behavior when a duplicate file is found. Valid values are "add", "preserve", and "fail". The default value is "add".

Reference jars outside of a jar [duplicate]

I am trying to build an executable jar program which depends on external jar downloaded. In my project, I included them in the build path and can be run and debug within eclipse.
When I tried to export it to a jar, I can run the program but I can't when I try to press a button which includes function calls and classes from the external jar. I have edited the environment variables (Windows XP) CLASSPATH to include paths of all the external jar, but it doesn't work.
A point to note is that I got compile warnings while exporting my executable jar, but it doesn't show up any description about the warnings.
Would someone kindly provide a thorough guide on how to include an external jar program using eclipse?
Eclipse 3.5 has an option to package required libraries into the runnable jar.
File -> Export...
Choose runnable jar and click next.
The runnable jar export window has a radio button where you can choose to package the required libraries into the jar.
You can do this by writing a manifest for your jar. Have a look at the Class-Path header. Eclipse has an option for choosing your own manifest on export.
The alternative is to add the dependency to the classpath at the time you invoke the application:
win32: java.exe -cp app.jar;dependency.jar foo.MyMainClass
*nix: java -cp app.jar:dependency.jar foo.MyMainClass
How to include the jars of your project into your runnable jar:
I'm using Eclipse Version: 3.7.2 running on Ubuntu 12.10. I'll also show you how to make the build.xml so you can do the ant jar from command line and create your jar with other imported jars extracted into it.
Basically you ask Eclipse to construct the build.xml that imports your libraries into your jar for you.
Fire up Eclipse and make a new Java project, make a new package 'mypackage', add your main class: Runner Put this code in there.
Now include the mysql-connector-java-5.1.28-bin.jar from Oracle which enables us to write Java to connect to the MySQL database. Do this by right clicking the project -> properties -> java build path -> Add External Jar -> pick mysql-connector-java-5.1.28-bin.jar.
Run the program within eclipse, it should run, and tell you that the username/password is invalid which means Eclipse is properly configured with the jar.
In Eclipse go to File -> Export -> Java -> Runnable Jar File. You will see this dialog:
Make sure to set up the 'save as ant script' checkbox. That is what makes it so you can use the commandline to do an ant jar later.
Then go to the terminal and look at the ant script:
So you see, I ran the jar and it didn't error out because it found the included mysql-connector-java-5.1.28-bin.jar embedded inside Hello.jar.
Look inside Hello.jar: vi Hello.jar and you will see many references to com/mysql/jdbc/stuff.class
To do ant jar on the commandline to do all this automatically: Rename buildant.xml to build.xml, and change the target name from create_run_jar to jar.
Then, from within MyProject you type ant jar and boom. You've got your jar inside MyProject. And you can invoke it using java -jar Hello.jar and it all works.
As a good practice you can use an Ant Script (Eclipse comes with it) to generate your JAR file. Inside this JAR you can have all dependent libs.
You can even set the MANIFEST's Class-path header to point to files in your filesystem, it's not a good practice though.
Ant build.xml script example:
<project name="jar with libs" default="compile and build" basedir=".">
<!-- this is used at compile time -->
<path id="example-classpath">
<pathelement location="${root-dir}" />
<fileset dir="D:/LIC/xalan-j_2_7_1" includes="*.jar" />
</path>
<target name="compile and build">
<!-- deletes previously created jar -->
<delete file="test.jar" />
<!-- compile your code and drop .class into "bin" directory -->
<javac srcdir="${basedir}" destdir="bin" debug="true" deprecation="on">
<!-- this is telling the compiler where are the dependencies -->
<classpath refid="example-classpath" />
</javac>
<!-- copy the JARs that you need to "bin" directory -->
<copy todir="bin">
<fileset dir="D:/LIC/xalan-j_2_7_1" includes="*.jar" />
</copy>
<!-- creates your jar with the contents inside "bin" (now with your .class and .jar dependencies) -->
<jar destfile="test.jar" basedir="bin" duplicate="preserve">
<manifest>
<!-- Who is building this jar? -->
<attribute name="Built-By" value="${user.name}" />
<!-- Information about the program itself -->
<attribute name="Implementation-Vendor" value="ACME inc." />
<attribute name="Implementation-Title" value="GreatProduct" />
<attribute name="Implementation-Version" value="1.0.0beta2" />
<!-- this tells which class should run when executing your jar -->
<attribute name="Main-class" value="ApplyXPath" />
</manifest>
</jar>
</target>
Try the fat-jar extension. It will include all external jars inside the jar.
Update url: http://kurucz-grafika.de/fatjar
Homepage: http://fjep.sourceforge.net/
look #
java-jar-ignores-classpath-Workaround

Build a jar in eclipse with jdbc driver [duplicate]

I am trying to build an executable jar program which depends on external jar downloaded. In my project, I included them in the build path and can be run and debug within eclipse.
When I tried to export it to a jar, I can run the program but I can't when I try to press a button which includes function calls and classes from the external jar. I have edited the environment variables (Windows XP) CLASSPATH to include paths of all the external jar, but it doesn't work.
A point to note is that I got compile warnings while exporting my executable jar, but it doesn't show up any description about the warnings.
Would someone kindly provide a thorough guide on how to include an external jar program using eclipse?
Eclipse 3.5 has an option to package required libraries into the runnable jar.
File -> Export...
Choose runnable jar and click next.
The runnable jar export window has a radio button where you can choose to package the required libraries into the jar.
You can do this by writing a manifest for your jar. Have a look at the Class-Path header. Eclipse has an option for choosing your own manifest on export.
The alternative is to add the dependency to the classpath at the time you invoke the application:
win32: java.exe -cp app.jar;dependency.jar foo.MyMainClass
*nix: java -cp app.jar:dependency.jar foo.MyMainClass
How to include the jars of your project into your runnable jar:
I'm using Eclipse Version: 3.7.2 running on Ubuntu 12.10. I'll also show you how to make the build.xml so you can do the ant jar from command line and create your jar with other imported jars extracted into it.
Basically you ask Eclipse to construct the build.xml that imports your libraries into your jar for you.
Fire up Eclipse and make a new Java project, make a new package 'mypackage', add your main class: Runner Put this code in there.
Now include the mysql-connector-java-5.1.28-bin.jar from Oracle which enables us to write Java to connect to the MySQL database. Do this by right clicking the project -> properties -> java build path -> Add External Jar -> pick mysql-connector-java-5.1.28-bin.jar.
Run the program within eclipse, it should run, and tell you that the username/password is invalid which means Eclipse is properly configured with the jar.
In Eclipse go to File -> Export -> Java -> Runnable Jar File. You will see this dialog:
Make sure to set up the 'save as ant script' checkbox. That is what makes it so you can use the commandline to do an ant jar later.
Then go to the terminal and look at the ant script:
So you see, I ran the jar and it didn't error out because it found the included mysql-connector-java-5.1.28-bin.jar embedded inside Hello.jar.
Look inside Hello.jar: vi Hello.jar and you will see many references to com/mysql/jdbc/stuff.class
To do ant jar on the commandline to do all this automatically: Rename buildant.xml to build.xml, and change the target name from create_run_jar to jar.
Then, from within MyProject you type ant jar and boom. You've got your jar inside MyProject. And you can invoke it using java -jar Hello.jar and it all works.
As a good practice you can use an Ant Script (Eclipse comes with it) to generate your JAR file. Inside this JAR you can have all dependent libs.
You can even set the MANIFEST's Class-path header to point to files in your filesystem, it's not a good practice though.
Ant build.xml script example:
<project name="jar with libs" default="compile and build" basedir=".">
<!-- this is used at compile time -->
<path id="example-classpath">
<pathelement location="${root-dir}" />
<fileset dir="D:/LIC/xalan-j_2_7_1" includes="*.jar" />
</path>
<target name="compile and build">
<!-- deletes previously created jar -->
<delete file="test.jar" />
<!-- compile your code and drop .class into "bin" directory -->
<javac srcdir="${basedir}" destdir="bin" debug="true" deprecation="on">
<!-- this is telling the compiler where are the dependencies -->
<classpath refid="example-classpath" />
</javac>
<!-- copy the JARs that you need to "bin" directory -->
<copy todir="bin">
<fileset dir="D:/LIC/xalan-j_2_7_1" includes="*.jar" />
</copy>
<!-- creates your jar with the contents inside "bin" (now with your .class and .jar dependencies) -->
<jar destfile="test.jar" basedir="bin" duplicate="preserve">
<manifest>
<!-- Who is building this jar? -->
<attribute name="Built-By" value="${user.name}" />
<!-- Information about the program itself -->
<attribute name="Implementation-Vendor" value="ACME inc." />
<attribute name="Implementation-Title" value="GreatProduct" />
<attribute name="Implementation-Version" value="1.0.0beta2" />
<!-- this tells which class should run when executing your jar -->
<attribute name="Main-class" value="ApplyXPath" />
</manifest>
</jar>
</target>
Try the fat-jar extension. It will include all external jars inside the jar.
Update url: http://kurucz-grafika.de/fatjar
Homepage: http://fjep.sourceforge.net/
look #
java-jar-ignores-classpath-Workaround

How to create testNG executeable .jar

I have a problem with testNG, how to create .jar(executeable) from testNG files. im using eclipse Luna.
Thanks
Your question is confusing. But I guess you want to generate jar file using testng where you have set of classes with different functionalities for automation testing.
Create testng class file which imports ITestListener or ISuiteListenerand implement functionality based on requirement.
Generate ant file with different targets where you can compile your code.
You have to set target for generate jar in ant xml file.
With this jar file you need to just import and set in other project's build path.
Now you can access whole functionalities created in jar.
Below code will be helpful to create executable jar into ant xml file.
<!-- compile-build is previous target. current build is depend on it. After compilation this build executed -->
<!-- directory-attrib is attribule to where you save your jar -->
<!-- bin.dir is you compiled class file, generally it is bin directory -->
<!-- version-num is version num specified by you -->
<property name="bin.dir" value="${basedir}/bin" />
<target name="build" depends="compile-build"
description="build and pack Jar API classes">
<jar destfile="${directory-attrib}/ur-jar-name.jar" basedir="${bin.dir}">
<manifest>
<attribute name="Built-By" value="${user.name}" />
<section name="Build-Info">
<attribute name="Version" value="${version-num}" />
</section>
</manifest>
</jar>
</target>
Generate build xml file and compile as Ant Build.

Including hibernate jar dependencies in ant build

I'm trying to compile a runnable jar-file for a project that makes use of hibernate. I'm trying to construct an ant build.xml file to streamline my build process, but I'm having troubles with the inclusion of the hibernate3.jar inside the final jar-file.
If I run the ant script I manage to include all my library jars, and they are put in the final jar-file's root. When I run the jar-file I get a
java.lang.NoClassDefFoundError: org/hibernate/Session
error. If I make use of the built-in export to jar in Eclipse, it works only if I choose "extract required libraries into jar". But that bloats the jar, and includes too much of my project (i.e. unit tests).
Below is my generated manifest:
Manifest-Version: 1.0
Main-Class: main.ServerImpl
Class-Path: ./ antlr-2.7.6.jar commons-collections-3.1.jar dom4j-1.6.1.jar
hibernate3.jar javassist-3.9.0.GA.jar jta-1.1.jar slf4j-api-1.5.11.jar
slf4j-simple-1.5.11.jar mysql-connector-java-5.1.12-bin.jar rmiio-2.0.2.jar
commons-logging-1.1.1.jar
And the part of the build.xml looks like this:
<target name="dist" depends="compile" description="Generates the Distribution Jar(s)">
<mkdir dir="${dist.dir}" />
<jar destfile="${dist.dir}/${dist.file.name}.jar" basedir="${build.prod.dir}" filesetmanifest="mergewithoutmain">
<manifest>
<attribute name="Main-Class" value="${main.class}" />
<attribute name="Class-Path" value="./ ${manifest.classpath} " />
<attribute name="Implementation-Title" value="${app.name}" />
<attribute name="Implementation-Version" value="${app.version}" />
<attribute name="Implementation-Vendor" value="${app.vendor}" />
</manifest>
<zipfileset refid="hibernatefiles" />
<zipfileset refid="slf4jfiles" />
<zipfileset refid="mysqlfiles" />
<zipfileset refid="commonsloggingfiles" />
<zipfileset refid="rmiiofiles" />
</jar>
</target>
The refids' for the zipfilesets point to the directories in a library directory lib in the root of the project. The manifest.classpath-variable takes the classpath of all those library jar-files, and flattens them with pathconvert and mapper.
I've also tried to set the manifest classpath to ".", "./" and only the library jar, but to no difference at all. I'm hoping there's a simple remedy to my problems...
Since you can't specify jar-inside-jar in your classpath, this way won't work.
You need either to jar only your code and then zip your jar with libs jars and launch script, like
#!/bin/sh
java -cp ./hibernate.jar:./mycode.jar... my.Main
(this what most people do), or you may unpack all your lib jars to the same dir which contains your compiled classes and then jar result dir back to single jar file (this what maven jar-with-dependencies packaging do).

Categories

Resources