PDA

View Full Version : Creating Java Manifest Files with Eclipse-or-anything-else




fishinatree
Jun 18, 2008, 01:26 AM
I'm trying to create a .jar file for a small Java program that I wrote, but I cannot get it to execute. I know that I need to create a manifest file, but I cannot find a tutorial anywhere that tells me how to do it clearly enough...
I created a folder called META-INF and inside have a file called MANIFEST.MF, which contains the lines:

Manifest-Version: 1.0
Created-By: 1.6.0 (Sun Microsystems Inc.)
Main-Class: gabe.ScanningApp

where gabe is the package name, and ScanningApp is the name of the class with the main method. I cd to where the files are, then use the terminal:

jar cfm gabe.jar META-INF/MANIFEST.MF *.class

i get the jar file, and when i use jar tf gabe.jar, I get a list of everything, but when I double click it, I get

java.lang.NoClassDefFoundError: ibbabble/src/gabe/ScanningApp

Should I have kept everything in that directory path instead of moving it to the desktop to package it in a .jar file? I'm very confused here...

|fishinatree|



lazydog
Jun 18, 2008, 05:11 AM
Hi, you can get Eclipse to create the manifest file for you when it creates your Jar file. Right click on a package and select Export, Jar file. From there you get a dialog and various options, some of which are to do with selecting your main class, saving the process as a Jar description file etc.


b e n

hazmatzak
Jun 18, 2008, 05:45 AM
Short answer with Eclipse:
Right-click the src directory of the project (so that you export all its packages)
Choose Export, and select "JAR file" under "Java"
Click Next to the third (last) page
Select "Generate the manifest file"
At the bottom, browse for the "Main class" (it shows only those classes with a main method)
Finish


Long answer with command line tools if you want to sort of understand how this works:

The first warning sign is that you used *.class at the end of the jar create command. That would only work on class files in the current directory, and put them at the root of the JAR. (A JAR is a ZIP, and all ZIPs have their own directory structure.) But since you put your class in a package -- as you should -- the class should be under the gabe directory in the JAR. What you must do is tell the jar utility to start JARing at the directory that contains the gabe directory.

You don't need to put the manifest in a file named MANIFEST.MF -- the jar utility will put any file you specify as META-INF/MANIFEST.MF. Therefore, you also don't need to put it anywhere special.

Because you want to tell the jar utility to JAR a directory, that directory must contain only class files (and other resources like images) -- no source files, otherwise they would go in the JAR too. The common practice is to put them in a bin directory. So in the directory ibbabble, your current directory, you should have this (bin is empty, javac will not create it):

bin/
src/
src/gabe/
src/gabe/ScanningApp.java

javac is not exactly straightforward in supporting this structure. You have to do something like this:

javac -d bin -sourcepath src src/gabe/ScanningApp.java

What this means is:
put the class files under the proper directories under bin
look for other source files in the proper directories under src
start compiling with the file src/gabe/ScanningApp.java

Because in this case you are only compiling one file, you really don't need the -sourcepath. But if for example, ScanningApp extended another class, javac would (or should) find it through the sourcepath; you don't have to list them all. But even if you do specify a sourcepath, you have to explicitly point to the file to compile (partly because the sourcepath can contain more than one directory).

After the compile, you should have:

bin/
bin/gabe/
bin/gabe/ScanningApp.class
src/
src/gabe/
src/gabe/ScanningApp.java

Create the manifest file somewhere convenient, like the current directory. You could call it scanning.mf:

scanning.mf
bin/
bin/gabe/
bin/gabe/ScanningApp.class
src/
src/gabe/
src/gabe/ScanningApp.java

Now the command would be:

jar cvfm gabe.jar scanning.mf -C bin .

v for verbose, if you want to see what it's doing
use the scanning.mf file in the current directory
then change to the bin directory
and include the contents of that directory (the dot) recursively

Note that the directory change happens inside the program only; the current directory of the shell does not change. If you then list the contents of the JAR with jar tf:

META-INF/
META-INF/MANIFEST.MF
gabe/
gabe/ScanningApp.class

That's what you want. The class is in exactly the right place. What if you had done:

jar cvfm gabe.jar scanning.mf bin

You would get:

META-INF/
META-INF/MANIFEST.MF
bin/
bin/gabe/
bin/gabe/ScanningApp.class

That's wrong. See the difference?

lazydog
Jun 18, 2008, 07:56 AM
^^^ An excellent reply. Worth reading for the mention of the -C option alone!
b e n

toddburch
Jun 18, 2008, 08:21 AM
Thanks so much for this thread. I've been wanting to learn how to do this. You guys ROCK!

Todd

fishinatree
Jun 19, 2008, 02:35 AM
hazmatzak :
Short answer with Eclipse:

1. Right-click the src directory of the project (so that you export all its packages)
2. Choose Export, and select "JAR file" under "Java"
3. Click Next to the third (last) page
4. Select "Generate the manifest file"
5. At the bottom, browse for the "Main class" (it shows only those classes with a main method)
6. Finish

I tried this, but i got
at gabe.ScanningApp.main(ScanningApp.java:14)
as an error on the Console. What am I doing wrong? I'll try compiling with the command line next, but I'd really prefer to be able to do it with Eclipse. Thanks for your input, everybody!

|fishinatree|

Edit: hazmatzak, you specified the code javac -d bin -sourcepath src src/gabe/ScanningApp.java, but what does -sourcepath mean? Do I type out the sourcepath "-something/someting/something/etc", or does -sourcepath refer to something else?

hazmatzak
Jun 19, 2008, 01:59 PM
When posting Java exceptions, include the first line, which says what the problem is, and the first few lines that follow (which start with "at"). If the exception stack has scrolled off, make the scroll buffer of the console bigger.

The -sourcepath is one or more directories in which to look for source. It's the same idea as the OS/shell's path: one or more directories to look for programs to run when you type their name. However, for the sourcepath, having only one directory is fairly common, since you often "root" all your source for a project in a single directory.

Compare it to the -classpath in the javac examples at the bottom of: http://java.sun.com/j2se/1.3/docs/tooldocs/win32/javac.html

You can point to each directory using its relative or absolute location. For example, if the source directory is /home/fish/ibbabble/src, you can always use that. If your current directory is /home/fish/ibbabble, you can use "src"; if the current directory is /home/fish, you can use "ibbabble/src"

foidulus
Jun 19, 2008, 02:53 PM
Ant is built into eclipse, so you don't need other tools, and you can customize it to your hearts content. Better yet, after you have the antfile done, its trivial to do your compile/jar building distribution in one step on the command line.

We do this at work and it saves TONS of time.