Accessing File In JAR

J

Jason Cavett

I am having trouble accessing files located in a JAR. Here's my
current setup (names have been changed of the JAR files).

JAR1.jar - This is the JAR that will try to access the text.properties
file. (This is a library that is being used by JAR2.jar)

JAR2.jar
- path/to/text.properties (this is the file I'm trying to access)


Here is the code I'm using to access the file.

URL propertiesUrl = ClassLoader.getSystemResource(DEFAULT_PATH +
FILE);

This works when I'm within Eclipse (most likely because the file is
not in a JAR from what I can tell.) However, as soon as I package up
the files into their respective JARs using ANT and I try to run the
executable jar (JAR2), I receive an error...

Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.IllegalArgumentException: URI is not hierarchical
at java.io.File.<init>(File.java:363)

Any suggestions about what to do here? I'm pretty confused about how
to fix this issue.


Thanks
 
M

Mark Space

Jason said:
URL propertiesUrl = ClassLoader.getSystemResource(DEFAULT_PATH +
FILE);
Any suggestions about what to do here? I'm pretty confused about how
to fix this issue.

Well, you could catch this exception and print out the values for
DEFAULT_PATH and FILE that cause it.

Also, a list of the relevant contents of JAR1.jar and JAR2.jar would be
helpful, since the most likely case is that you've just got a
misspelling in there someplace.
 
M

Mike Schilling

Mark said:
Well, you could catch this exception and print out the values for
DEFAULT_PATH and FILE that cause it.

Also, a list of the relevant contents of JAR1.jar and JAR2.jar would
be helpful, since the most likely case is that you've just got a
misspelling in there someplace.

Very possibly a case-related problem. In a Windows filesystem
dir/A.txt and dir/a.txt are the same, but inside a jar file they're
different.
 
J

Jason Cavett

Very possibly a case-related problem.  In a Windows filesystem
dir/A.txt and dir/a.txt are the same, but inside a jar file they're
different.

Unfortunately, it's neither of these problems. When I run via
Eclipse, it works great. Via ANT...it doesn't. I figured it's
because it can't access the data across JAR files...but...that doesn't
sound right (since they're all loaded on the same classpath).

This is extremely frustrating. I appreciate help so far, but I'm
still stuck.
 
M

Martin Gregorie

This is extremely frustrating. I appreciate help so far, but I'm still
stuck.
When you run a program that is in a jar file any externally set CLASSPATH
is ignored. The manifest file in the jar file must provide two pieces of
infomation:
(1) the name of the class containing the main() method
(2) a list of the jar files to be accessed.

Each jar file may be specified as an absolute or relative path. The
easiest way to do this is to put both jar files in the same directory and
set up the manifest to match. In your case it would be something like
this:

-----manifest in jar1.jar------

Main-Class: ClassWithMainMethod
Class-Path: jar2.jar

-------end of manifest---------

Is your manifest anything like this?
 
A

Arne Vajhøj

Jason said:
I am having trouble accessing files located in a JAR. Here's my
current setup (names have been changed of the JAR files).

JAR1.jar - This is the JAR that will try to access the text.properties
file. (This is a library that is being used by JAR2.jar)

JAR2.jar
- path/to/text.properties (this is the file I'm trying to access)


Here is the code I'm using to access the file.

URL propertiesUrl = ClassLoader.getSystemResource(DEFAULT_PATH +
FILE);

This works when I'm within Eclipse (most likely because the file is
not in a JAR from what I can tell.) However, as soon as I package up
the files into their respective JARs using ANT and I try to run the
executable jar (JAR2), I receive an error...

Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.IllegalArgumentException: URI is not hierarchical
at java.io.File.<init>(File.java:363)

Any suggestions about what to do here? I'm pretty confused about how
to fix this issue.

What values does DEFAULT_PATH + FILE have ?

How does the line throwing the execption look like ?

Arne
 
J

Jason Cavett

When you run a program that is in a jar file any externally set CLASSPATH
is ignored. The manifest file in the jar file must provide two pieces of
infomation:
(1) the name of the class containing the main() method
(2) a list of the jar files to be accessed.

Each jar file may be specified as an absolute or relative path. The
easiest way to do this is to put both jar files in the same directory and
set up the manifest to match. In your case it would be something like
this:

-----manifest in jar1.jar------

Main-Class: ClassWithMainMethod
Class-Path: jar2.jar

-------end of manifest---------

Is your manifest anything like this?

Those look like this in my Manifest file.
 
M

Martin Gregorie

Those look like this in my Manifest file.
No, that would be correct provided that the jar file you previously
called 'jar2.jar' is now called 'lib-0.1.jar' and in a directory whose
relative pathname (from the directory containing the jar file containing
the manifest) is 'lib', i.e. something like this (using your original
file names):

/jarlib/lib/jar2.jar
/jarlib/jar1.jar


Please stick to the names you used when you first described the problem.
It would have been better if you'd used actual file names: changing names
in mid-thread just makes problem diagnosis harder.
 
J

Jason Cavett

No, that would be correct provided that the jar file you previously
called 'jar2.jar' is now called 'lib-0.1.jar' and in a directory whose
relative pathname (from the directory containing the jar file containing
the manifest) is 'lib', i.e. something like this (using your original
file names):

/jarlib/lib/jar2.jar
/jarlib/jar1.jar

Please stick to the names you used when you first described the problem.
It would have been better if you'd used actual file names: changing names
in mid-thread just makes problem diagnosis harder.

Sorry about that.

Anyway, I did figure out what the problem was.

The main issue is that, when I'm running from Eclipse, the files I am
accessing are in a folder. However, when I'm accessing via an Ant
build/run, the files I want to access are in a JAR file.

I was originally trying to access the files via
ClassLoader.getSystemResource(DEFAULT_PATH + FILE); However, I
instead needed to do ClassLoader.getSystemResourceAsStream
(DEFAULT_PATH + FILE); and it worked fine. I understand why now, but
it's a bit confusing/stupid that there are multiple ways to access
files and they are not all consistent. For example, my icons (which
are located in the same location as FILE) I load via
ClassLoader.getSystemResource(), but I cannot do the same thing with a
text file.

Either way, it now works and I wanted to share the information. Hope
it helps someone else.
 
A

Andrew Thompson

....
Those look like this in my Manifest file.

What Martin referred to as ClassWithMainMethod
and you called path.to.Main, I would describe as
the 'fully qualified class name'. It does NOT
include the path to the main class, just its
package and classname, in the form
'java.lang.Object'.

And further to what Martin was saying, please
stop wasting your time by 'pararaphrasing' details
in the manifest. Copy/paste is best.
 
M

Martin Gregorie

I understand why now, but it's a bit
confusing/stupid that there are multiple ways to access files and they
are not all consistent.
Its not so stupid: in general the development directory structure is more
complex than the deployment structure and understandably so: basically
you want to throw the jar files (your application jar plus any support
jars that are not part of the JRE) into one or two directories on the
target host and have it run. That's what the manifest makes possible
provided you've defined the application appropriately.

In my application jar I have the class containing main() in the base
directory where the jar file is built. This directory also contains a few
configuration files. The development environment defines the classpath
via the CLASSPATH environment variable. Both classfiles and config files
are included in the jar file.

From the base development directory the command "java MainClass
arguments" runs the application using the CLASSPATH and ignoring the
manifest.

After installation, provided only that CLASSPATH lists the application
jar file, the "java -jar appjar-class-name MainClass arguments" command
runs the application. The manifest lists the required support jar files
as well as naming the main class. Simple to set up and very simple to
run in both environments.

The config file(s) are opened as "./configfile" using a BufferedReader:
this works as expected in both environments, but note that the './'
prefix is needed. I imagine a similar trick would work for image files.
 

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

Forum statistics

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

Latest Threads

Top