• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Help please...jar problem

 
Ranch Hand
Posts: 276
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have an application that I wish to distribute in a single executable jar file. This jar file needs to contain another jar file (jtds jdbc driver).

I placed the jtds jar file (jtds-0.8.jar) in the top directory of the jar file that I create.

For example the structure looks something like this:

com (directory holding my package)
META-INF (directory holding the manifest)
jtds-0.8.jar
mainclass.txt (tells what the main class is...com.mycompany.product.MyApp for example)

When I try to run the application like this:

java -classpath jtds-0.8.jar -jar myapp.jar

I get a NoClassDefFoundError: net/sourceforge/jtds/jdbc/Driver error.

This runs just fine through JBuilder, so I know everything is set up right outside of the jar, and since the application continues after the exception and runs as expected (without jdbc working of course) I know that the manifest is set up right.

So, how can I tell java that there is a jar inside of the jar it needs?

THANKS!
[ July 29, 2004: Message edited by: Darrin Smith ]
 
Darrin Smith
Ranch Hand
Posts: 276
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
OK, here is something that I thought would work, but it isn't quite there...

I've read that a jar within a jar just won't work, so I extracted the jtds jar to the same directory as my com so it looks like this

com (my app)
net (jtds)


It still doesn't work this way , although I would think that there should be a way to do it like this...expand the jar that is.

So, how do I set up the manifest Class-Path to let it know that the files needed are located within the jar itself?

I never have a problem running this in JBuilder because I keep the jtds as a jar there and set the classpath explicitly (C:\.....jtds-0.8.jar), but I can't do that here since a jar within a jar won't work, so I am trying to get it to work with with the jtds driver unjarred.

Thanks!

[ July 29, 2004: Message edited by: Darrin Smith ]
[ July 29, 2004: Message edited by: Darrin Smith ]
 
Ranch Hand
Posts: 1923
Scala Postgres Database Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well - I'm guilty in telling people, that a jar inside a jar will not work.
But it does.

You simply write into the Manifest:

if I remember right, and the syntax is correct.
 
Darrin Smith
Ranch Hand
Posts: 276
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well I tried what you said and it worked for the jtds jar file just fine!

The only problem is I need to have an two additional jar files packaged as well, and I cannot get it to work when I add those (NoClassDefFound on a class inside of the second jar...the jtds classes are still found).

I've tried the following:

Class-Path: jtds-0.8.1.jar jar2.jar jar3.jar

Class-Path: jtds-0.8.1.jar
Class-Path: jar2.jar
Class-Path: jar3.jar

Class-Path: jtds-0.8.1.jar; jar2.jar; jar3.jar

The last two prevent the jtds jar from being found while the first one sees the jtds jar but not the others

Does anyone know the proper syntax (I thought the first example was supposed to be correct, but it didn't work).

Thanks!
 
Stefan Wagner
Ranch Hand
Posts: 1923
Scala Postgres Database Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well - I tried to proofe my statement, but I either I don't get it right, or it's not possible.

I lost my harddrive with my last test - where I thought it's possible, and may not look, if my TEST was wrong.

I found at least an adress, where they claim to have build a classloader to handle nested jars:

http://classworlds.codehaus.org/uberjar.html

I'm not sure, whether this is open source - looks like.
 
Sheriff
Posts: 9109
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Does anyone know the proper syntax

According to Sun,
Class-Path: servlet.jar infobus.jar acme/beans.jar
should work.
 
Stefan Wagner
Ranch Hand
Posts: 1923
Scala Postgres Database Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
As far as I have tested and after reading multiple threads, (i.e.: at forum.java.sun.com: jar, where this is a topic every two weeks) - the classpath inside the jar refers to the outer filesystem. (see Marilyns link).

Therefor it seems to work, if you don't delete your jar's outside of the nesting jar - the outer jars are found and used.

But what's the sense of an classpath inside the jar? The location of jars on foreign machines might be very different!

I guess, it makes only sense, if you use that classpath to avoid very long commandlines, and ship those jars and install them in a specific location, and refer to them relative to your main-jar.

Or you ship it to customers, who are able and willing to manipulate the jar and it's classpath by themself.

I wrote a brief script to test the classpath of an inner jar - it was meant as ultimate proof to show that nested jars are possible.
But it turned out, that it's more an indiz, that nested jars will not work.
It's creating 5 java-source files, compiles them, put's them into 3 jars, and 2 of these jars into the third.
Creates the manifest and archives it, removes the source and classes and the unnested jars.
Runs the application, and on failure it shows the content of the nested jar and prints the Manifest.
Then cleans up everything except itself.

It's written for linux/bash and might need modifications for other shells.
I suggest creating a new directory for it to test it out

Perhaps somebody likes to translate it to a windows/batch syntax:
# = REM
rm = del
cat= type
if CONDITION ; then EXPRESSION ; fi = ??? (fi is a kind of 'end if')
-d x = ?? (is there a directory x ? true : false)
&&, || : short-curcuit evaluation of AND and OR, pretty much as in java.



If there is still someone believing, you may call a jar inside a jar - without changing the classloader, or using 'java.util.jar' to unjar these jars, I would be thankful for a proof, or a hint, where my script goes wrong.

If your output is '15' without dirty tricks, you got it done.

To see it work: comment out the last line, and run:

or

on win-plattform.

[ July 31, 2004: Message edited by: Stefan Wagner ]
[ July 31, 2004: Message edited by: Stefan Wagner ]
 
Darrin Smith
Ranch Hand
Posts: 276
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
A little update....

At the suggestion of another person, I tried my test on a clean machine that never had jtds put on it, and sure enough....NoClassDefFoundError.

So, it looks like the final word (as others seem to indicate here also) is that nested jars just don't work.

Given that, I thought about expanding the jars inside of the main jar. I tried that as a quick test, but still got the NoClassDefFoundError, so there must be something you need to do with the classpath as well.

My struture looks like this:

com
---->mycompany
-------->myproject
---->thirdparty1
-------->thirdpartyproject
net
---->sourceforge
-------->JTDS
mainclass.txt

Anyone hazard to guess how the classpath should be set up for something looking like this?
 
Stefan Wagner
Ranch Hand
Posts: 1923
Scala Postgres Database Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
untested suggestion: make a common parent 'classes':

move one level up.
jar -f myJar -C classes .
no classpath needed.

Did I say untested?
An ant-template with a list of foreign jars, to be extracted and commonly compressed, may help to make it work, test, improve, and then use it for years without too much anger
 
Ranch Hand
Posts: 1608
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


I'm guilty in telling people, that a jar inside a jar will not work.



Let's make this right. A JAR inside a JAR is not accessible by the system classloader simply by adding a manifest entry.

This doesn't prevent you from writing your own class loader that loads classes from jars within jars (potentially by reading a manifest entry). Heck, why not write one that loads classes from zips inside tars inside gzips inside jars that are located on a HTTP server which is on the moon that acts as a gateway to a FTP server on Mars?
Loading classes from ${any-location} will always "work" provided you have a class loader that is capable of doing it.
 
Ranch Hand
Posts: 299
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I had a similar problem with one of my apps. What I eneded up doing was putting all my classes plus the two 3rd-party jars into a single jar by having an Ant task extract the 3rd-party jars to my target directory then jarring up the contents. Works fine for me with 2 different apps. If anyone wants to see the apps and/or the ant build file that does it, let me know. Email me at pipasoft.com and use my first name in the email address.

brian
reply
    Bookmark Topic Watch Topic
  • New Topic