Library jar into executable jar

Hi guys!

I’m trying to develop a nice game resource manager for my game and I’m having a little problem:

I’m using jdom to work with xml files and I want to include it to the executable jar somehow. The problem is - whatever I’m trying to do I get a


Exception in thread "main" java.lang.NoClassDefFoundError: org/jdom/JDOMException

Actually I cannot launch my editor from jar (no way!).

I’ve tried something like this:


C:\apps\eclipse\workspace\MRM\final>java -cp c:\apps\jars\jdom.jar -jar MRM.jar
Exception in thread "main" java.lang.NoClassDefFoundError: org/jdom/JDOMException

C:\apps\eclipse\workspace\MRM\final>java -cp c:\apps\jars\jdom.jar;. -jar MRM.ja
Exception in thread "main" java.lang.NoClassDefFoundError: org/jdom/JDOMException

There is no problem launching unpacked version of this soft…

Actually there is a solution: copy all needed library classes to the root of the executable jar. But this solution is not very good.

Plz help.

You must edit your jar’s manifest and add the line Class-Path: path-tojdom

I’ve tried to add Class-Path to jar… Still it doesn’t work. My manifest file looks like that:

Manifest-Version: 1.0
Main-Class: ua.com.attacksoftware.mrm.MRM
Class-Path: c:\apps\jars\jdom.jar

By the way what class path should I write to manifest if a library jar is nested inside the executable jar?

Does Java support nested jars at all? Is it possible to create a single jar if my app uses third-party libraries?

Huzzah!

Another opportunity to pimp GenJar. It makes all of this jar-generation malarkey completely trivial.

Why not do something like this?

java -cp jdom.jar;MRM.jar your.MainClass

IIRC, the -jar parameter overrides -cp which would explain why jdom can’t be found

Yep. It’s braindead, and has confused many many people over the years - but it IS in Sun’s docs; classpath is completely ignored whenever you use -jar.

[quote]IIRC, the -jar parameter overrides -cp which would explain why jdom can’t be found
[/quote]
Great! Thnx, that is really great info!

[quote]Why not do something like this?

java -cp jdom.jar;MRM.jar your.MainClass

[/quote]
All is simple… I’m writing this software for non-tech-guys. They are just game balance testers and everything they know about Java is that it is a nice coffee… Becasue of that I want to make installation and run processes as easy as possible.

As confusing as it is, it really IS logical if you thin kabout it.

-classpath is defined as just repalcing the environment CLASSPATH

-jar is made for app packages that are all self contained where you DON’T want the environment screwing with or changing how they execute

That coudl be even more confusing.

If -jar and -cp are mutually exclusive, then it is an error if a command-line invocation includes both.

As such, the java executable should throw an error indicating this.
It would resolve all confusion in the matter.

Perhaps someone could put forward an RFC for this?

one thing you could do is when you figure out how to launch correctly at command line, create a batch file they can double click, or make and executablet hat does that (however you do that lol) thats what eclipse and azureus and other java made applications work.

[quote]one thing you could do is when you figure out how to launch correctly at command line, create a batch file they can double click…
[/quote]
Actually this is the the best solution I’ve found so far.

Can you explaine in a bit more detail? Is there a specialized tool for doing that?

Okay, found a way to go about converting your batch file into an executable

theres to link to a program that does it (dunno if it cost money) if it does, just do a google search for “batch compilers”

good luck =D

What I have done to make executable jars is write a little ant script that will expand my library jars into a tmp folder, then make an executable jar, then wipe out the tmp directory. Using an ant build script from within Eclipse, it looks a bit like this:

<property name="my.jar" location="${basedir}/WhateverYouLike.jar"/>
<property name="tmpdir" location="${basedir}/__tmp__"/>
<property name="lib" location="${basedir}/lib"/>
<property name="manifest" location="${basedir}/MANIFEST.MF"/>

<!-- The non-jar resources to be put into the executable jar -->
<property name="classes" location="${basedir}/classes"/>
<property name="resources" location="${basedir}/resources"/>
  <unjar dest="${tmpdir}">
    <fileset dir="${lib}">
      <include name="*.jar"/>
    </fileset>
</unjar>

	<!-- Create a new JAR file -->
	<jar destfile="${my.jar}" manifest="${manifest}">
		<fileset dir="${tmpdir}" excludes="**/META-INF/**"/>
		<fileset dir="${classes}"/>
		<fileset dir="${resources}"/>
	</jar>
	
	<!-- Remove the temporary files -->
	<delete dir="${tmpdir}"/>
</target>

Sorry, Jeff, but he’s right :).

I’m not referring to “the original thinking behind the possibility of architecting the back-end the way it was” as braindead - but making the most important and most used tool in the java platform so counter-intuitive (and, techincally, wrong as per above) from a user perspective.