Executable JAR ClassPath problem

P

Pito Salas

Here's my Manifest.mf for what is supposed to be an executable JAR. It
doesn't work at all and I've been experimenting like crazy and looking for
information on the web and have not been able to solve it (and I think it's
something really trivial.)

Manifest-Version: 1.0
Main-Class: com.salas.bb.core.ApplicationLauncher
Class-Path: lib/binding-0.9.6.jar
bin
bin/com/salas/bb/ai
bin/com/salas/bb/channelguide
bin/com/salas/bb/core
bin/com/salas/bb/dialogs
bin/com/salas/bb/views
bin/com/salas/bb/utils
bin/resources
lib/castor.jar
lib/cglib.jar
lib/commons-collections.jar
lib/commons-lang.jar
lib/commons-logging.jar
lib/dom4j.jar
lib/ehcache.jar
lib/forms-1.0.2.jar
lib/hibernate2.jar
lib/htmlparser.jar
lib/hsqldb.jar
lib/jdbc2_0-stdtext.jar
lib/informa.jar
lib/jdom.jar
lib/jta.jar
lib/looks-1.1.3.jar
lib/lucene.jar
lib/odmg.jar
lib/uif-1.2b6.jar
lib/xalan.jar
lib/xerces.jar
lib/xml-apis.jar
lib/xmlrpc-1.2.b1.jar

If I look inside the Jar with PKUnzip I see: the indicated JARs inside the
indicated directory: lib; The application's own .CLASS files as well as some
properties files are found in the directories bin, and bin/com/salas/bb/ai
bin/com/salas/bb/channelguide, etc.

What happens when I launch with java -jar blogbridge.jar is that I get a
missing class, which I happen to know is in the
directorybin/com/salas/bb/core.
Exception in thread "main" java.lang.NoClassDefFoundError:
com/jgoodies/swing/convenience/DefaultApplicationStarter
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
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)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)

Also I can tell that a logging.properties file which lives in the same
directory is not being seen.

The first line in the app prints out the classpath and when I fool the app
into running it prints that the classpath is blogbridge.jar and nothing
more.

Can someone please help??? I suspect its a trivial problem!

Thanks
 
D

Dave Glasser

Here's my Manifest.mf for what is supposed to be an executable JAR. It
doesn't work at all and I've been experimenting like crazy and looking for
information on the web and have not been able to solve it (and I think it's
something really trivial.)

Manifest-Version: 1.0
Main-Class: com.salas.bb.core.ApplicationLauncher
Class-Path: lib/binding-0.9.6.jar
bin
bin/com/salas/bb/ai
bin/com/salas/bb/channelguide
If I look inside the Jar with PKUnzip I see: the indicated JARs inside the
indicated directory: lib; The application's own .CLASS files as well as some

Jar files referenced by your Class-Path header need to be *outside*
the main jar file. The entries in the Class-Path header are paths
relative to the location of the main jar file itself. If you run this
command on your jar file, from the directory where it's located:

jar xvf myjar.jar lib

It should extract those jars into the correct location.

This is a FAQ. Many people want to be able to bundle their application
along with all needed jars into one simple, neat jar file, but
unfortunately, it's not possible using the Class-Path header. (Or any
other way I'm aware of.) You could extract all files from all jars and
then re-jar them into a single jar file, but that would be messy.
 
H

hiwa

Principle of Error-less Executable Jar
(1)Entry delimiter must be space, not newline.
(2)Only subdirectories which contain resources(texts, images etc.) are
allowed.
(3)Classes specified by Class-Path must be in a jar or jars. In other
word, you can only specify those jar files, not raw classes nor raw
subdirectories which contain classes.
(4)Preferably, put all jars onto the flat current directory.

A Safest example:

Class-Path: aaa.jar bbb.jar /images /properties
 
T

Tony Morris

You might want to investigate the possibility of a custom ClassLoader.

--
Tony Morris
(BInfTech, Cert 3 I.T., SCJP[1.4], SCJD)
Software Engineer
IBM Australia - Tivoli Security Software
(2003 VTR1000F)
 
P

Pito Salas

Hiwa,

Thanks. I am still having problems. Here is my manifest.mf which looks like
your "safest example"

Manifest-Version: 1.0
Main-Class: com.salas.bb.core.ApplicationLauncher
Class-Path: blogbridge.jar blogbridgelibs.jar

And now my jar has very little in it. The above two jars and the meta-inf
folder with the manifest in it.

Note that blogbridge.jar has inside itself a subdirectory tree
Note that blogbridgelibs.jar inside itself a series of .jars (which each may
have a subdirectory tree.)
Note that the indicated main-class lives inside the jar called
"blogbridge.jar", at a subdirectory a couple of levels deep:
com/salas/bb/core/ApplicationLauncher.class

I get this error:
C:\temp>java -jar bbexec.jar
Exception in thread "main" java.lang.NoClassDefFoundError:
com/salas/bb/core/ApplicationLauncher

What am I doing wrong?

In the end I want a self-contained .jar which includes my program plus a
bunch of open source library jars which will execute. I don't care if it
takes multiple steps to build it. Did you notice that the other person
responding to my post said what I was trying to do was impossible?

Thanks,

Pito
 
D

Dave Glasser

Hiwa,

Thanks. I am still having problems. Here is my manifest.mf which looks like
your "safest example"

Manifest-Version: 1.0
Main-Class: com.salas.bb.core.ApplicationLauncher
Class-Path: blogbridge.jar blogbridgelibs.jar

And now my jar has very little in it. The above two jars and the meta-inf
folder with the manifest in it.

Note that blogbridge.jar has inside itself a subdirectory tree
Note that blogbridgelibs.jar inside itself a series of .jars (which each may
have a subdirectory tree.)
Note that the indicated main-class lives inside the jar called
"blogbridge.jar", at a subdirectory a couple of levels deep:
com/salas/bb/core/ApplicationLauncher.class

I get this error:
C:\temp>java -jar bbexec.jar
Exception in thread "main" java.lang.NoClassDefFoundError:
com/salas/bb/core/ApplicationLauncher

What am I doing wrong?

Attempting something that's not possible.
In the end I want a self-contained .jar which includes my program plus a
bunch of open source library jars which will execute. I don't care if it
takes multiple steps to build it. Did you notice that the other person
responding to my post said what I was trying to do was impossible?

And it's still true.
 
P

Pito Salas

Ok, Ok, Dave. I am sorry I doubted you :)
Forgive me for grasping at straws :)

It's just that it's really contradicting what everyone seems to think is
possible with executable jars.

What is the key impossible thing?

Is it that an executable jar can never locate other jars in itself without a
custom classloader?

So you are forced to have some kind of install program then?

- Pito
 
D

Dale King

Pito Salas said:
Ok, Ok, Dave. I am sorry I doubted you :)
Forgive me for grasping at straws :)

It's just that it's really contradicting what everyone seems to think is
possible with executable jars.

What is the key impossible thing?

Is it that an executable jar can never locate other jars in itself without a
custom classloader?

Yes, you cannot have jars inside of other jars and have them be in the
classpath. Even if you could it would be a very bad idea. A jar file is a
zip file. It gives you random access as far as selecting which file you want
to read, but you only get sequential access to the data within that file,
because it could be compressed. This works fine for class loading because
you only want to open the file for the class you are loading. But once you
put a jar inside another jar you only have sequential access to the jar
file. That means to load a single file from it requires reading the entire
jar instead of just the one file.
So you are forced to have some kind of install program then?

It depends what you want to do. For many things zip is sufficient.
 
P

Pito Salas

Dale,

Excellent explanation. That makes perfect sense.

Can you advise me on the 'best practice' for what I am trying to do:

I want to meet these requirements:

1) I have an application which uses a bunch of libraries (e.g. xerces etc.)
which are distributed as .jars.
2) a single file to distribute my application. I don't want to ask my user
to know what the heck a jar is or xerces is

I was hoping to just be able to 'run' that file. Is there a way of achieving
that, or am I forced to have an 'install' step then?

- Pito
 
J

Jim Sculley

Pito said:
Dale,

Excellent explanation. That makes perfect sense.

Can you advise me on the 'best practice' for what I am trying to do:

I want to meet these requirements:

1) I have an application which uses a bunch of libraries (e.g. xerces etc.)
which are distributed as .jars.
2) a single file to distribute my application. I don't want to ask my user
to know what the heck a jar is or xerces is

I was hoping to just be able to 'run' that file. Is there a way of achieving
that, or am I forced to have an 'install' step then?

Use Java WebStart.

Jim S.
 
D

Dave Glasser

Dale,

Excellent explanation. That makes perfect sense.

Can you advise me on the 'best practice' for what I am trying to do:

I want to meet these requirements:

1) I have an application which uses a bunch of libraries (e.g. xerces etc.)
which are distributed as .jars.
2) a single file to distribute my application. I don't want to ask my user
to know what the heck a jar is or xerces is

I was hoping to just be able to 'run' that file. Is there a way of achieving
that, or am I forced to have an 'install' step then?

As I said before, you can merge the contents of all of your jar files
into a single jar file, and you wouldn't even need the Class-Path
header for it to work. That would put the burden on you (to build the
single jar file) instead of your users.

Another thing would be to have your app, upon startup, look for the
library jars in their prescribed locations. Any it didn't find, it
could quietly extract from the application jar file into the correct
location using regular API calls. If the jars aren't present on
application startup though, the app might need to be restarted for
them to be visible to the system classloader, however. I don't know.
If that's the case, maybe you could quietly (unknown to the user) fork
a new JVM after the jars were extracted, like Ant forks a JVM for
certain tasks. The new JVM would have access to the extracted library
jars. (As I said, though, that might not be necessary.)

Having said all that, I'll also say that I think you're worrying too
much about distributing multiple jar files. Users understand that apps
don't always come packaged in a single file, in fact most Windows apps
include any number of DLLs that are installed to various locations
like the system directory.

Finally, I suggest you check out the free, GPL Java installer program
called IZPack, which is available at http://www.izforge.com/izpack/ .
It makes installing Java apps very simple and will handle all of the
library jars very nicely.
 
Joined
Jul 29, 2011
Messages
2
Reaction score
0
Regarding the jar inclusion problem in classpath

When I tried to execute java -classpath = *.jar RuleClient.jar with all jar files in the same directory where the main jar exists. When i execute the above command, i m getting the following error. Instead of recognizing the jar file with version for example 1.1.1, it recognizes as 1/1/1. Pls suggest how to avoid this issue.

Exception in thread "main" java.lang.NoClassDefFoundError: abdera-core-1/1/1/jar
Caused by: java.lang.ClassNotFoundException: abdera-core-1.1.1.jar
 
Joined
Mar 8, 2012
Messages
1
Reaction score
0
Solution for this problem

I was also facing the same issue:
Abc.jar had my main class and this class also requires libraries from x.jar, y.jar nad z.jar which are packaged inside the Abc.jar.

The Manifest.MF inside the Abc.jar has the classpath as:
Class-Path: x.jar y.jar z.jar

When I run the Abc.jar using: java -jar Abc.jar, I see errors while loading the classes which are reffered in the main class.

If you have the x.jar, y.jar and z.jar beside the Abc.jar, it would run property.

But, my requirement was to package all the dependent jars also inside the Abc.jar.

For this, I used Eclipse's solution. When you export a Java Project from Eclipse, and mark it as Runnable Jar specifying your Main class, all the dependent Jar files will be packaged into the resultant Runnable Jar file and there are 5 classes that are added by Eclipse. Apart from these classes, Eclipse modifies the Manifest.MF file to add the following parameters:

Rsrc-Class-Path: ./ x.jar y.jar z.jar
Class-Path: .
Rsrc-Main-Class: com.dwij.sample.Sample
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader

Here, Eclipse is using the concept of URL Class loaders. This manifest file will be read and your actual Main class will be called after pointing the classpath to the Jars files mentioned in the "Rsrc-Class-Path" property.

I included these classes in my source project, compiled and archived.

That works like a charm!

I have composed a blog post about this in my blog here:
http://techie-lucky.blogspot.com.au/2012/03/solution-for-issue-with.html

Please let me know your comments.

Thanks,
Tilak
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top