Using JARs
There are many resources on the web for how to use JARs.
Usually they are focused on default JARs features.
The class
JarClassLoader
provides new features that may change the way a developer uses JARs.
JAR files are used to deploy Java application.
For example, you have completed development of some very complex MyApp application.
Most probably you will generate MyApp.jar with all your Java classes
required by your application resources.
Where do you keep other dependent required resources?
To JAR or not to JAR?
The general approach to answer this question should be the following:
put everything you are not exposing to your user in a JAR.
In other words, leave out of a JAR only those files that are allowed to be
modified by a user. Examples of files to be kept out of the JAR are
log4j.properties - the logger properties file.
This file (or similar files) is included in your application distribution if you are
using Log4J package for logging.
In many cases users are allowed to modify this file if different level of logging are required.
-
MyApp.properties - the application properties file.
In many cases this file is allowed to be modified by user. Move this file
(if it exist) into JAR if you do not allow a user to modify it.
How to deal with dependent JARs
in conventional deployment
In conventional deployment without the use of the
JarClassLoader
you have the following options:
How to deal with dependent JARs using
JarClassLoader
Very simple: just add third party JARs directly into your main root JAR.
The location of these JARs in the main root JAR does not matter.
You could put them into any folder, for example lib folder
or even into another JAR (nested JAR).
Any JAR in the main root JAR is considered to be in the classpath of the main application.
The
JarClassLoader
allows to have nested JARs, i.e to have JARs in the JAR.
This is very convenient for projects with complex dependencies.
For example,
Hibernate
distribution has about 20 JAR files. It includes JARs and license files.
You could safely put all of them into a single JAR for nice encapsulation
and add this single JAR into your main root JAR.
How to deal with native libraries
in conventional deployment
In conventional deployment without use of the
JarClassLoader
you actually do not have any options.
You must know exact the location of the native library
and provide this location to the VM via java.library.path
system properties entry, or environment variable,
or by putting the native library into some system default location.
Having native libraries in your distribution package exposes dependencies of your application,
clutters the distribution package,
and adds the possibility for your application to fail if these native libraries are missing or replaced.
Problems with loading native libraries are very common and difficult to debug.
The VM complains with
java.lang.UnsatisfiedLinkError
which does not give any clue as to what may cause this problem.
You could do very little while supporting your customers online with this kind
of problem. Your support ends up with a try this or try that approach.
How to deal with native libraries using
JarClassLoader
Very simple: just put native libraries directly into your main root JAR.
The native library could be in the Windows or *nix format and will be loaded
appropriately on a proper platform.
The location of these native libraries in the main root JAR does not matter.
You could put them into any folder,
for example lib folder or even into another JAR (nested JAR).
Any native library in the main root JAR is considered to be in the native libraries path
of the main application and will be loaded by the class loader.
This design approach guarantees that you will not have any problems with loading native libraries.
How to load other resources
Loading resources from a JAR or a file system with
JarClassLoader
or system class loader is identical. Here are some examples:
Loading an image
ImageIcon img = null;
URL url = getClass().getClassLoader().getResource("MyApp.gif");
if (url != null) {
img = new ImageIcon(url);
}
|
Reading a file
String fileName = "resource/Sample.txt";
try {
InputStream is = getClass().getClassLoader().getResourceAsStream(fileName);
if (is == null) {
throw new FileNotFoundException(fileName);
}
BufferedReader br = new BufferedReader(new InputStreamReader(is));
for (int i = 1; ; i++) {
String s = br.readLine();
if (s == null) {
break;
}
System.out.println("Line-" + i + ": " + s);
}
} catch(IOException e) {
System.out.println("Cannot read file '" + fileName + "':" + e);
}
|
|