JavaTM Programming Language Basics, Part 2
Lesson 7: Packages and JavaTM Archive File Format
[<<BACK] [CONTENTS] [NEXT>>]
Until now, you have used classes from the Java API library by
importing the package containing the class or classes you need.
A package is a convenient way to organize groups of related classes,
and in development, you should organize your application
files into packages too. Packages make it easier to locate
and use the class files and help you control access to class data
at run time.
When your application is fully tested, debugged, and ready
for deployment, use the JavaTM Archive file format to
deploy the application. JAR file format is a compression
and file packaging format and tool for bundling executable
files with any other related application files so they can
be deployed as one unit.
This lesson shows you how to organize the program files from
Part 2, Lesson 6: Internationalization into
packages and deploy the executable and other related files to
production using JAR file format. Normally, you would use packages
from the beginning of development.
Setting up Class Packages
It is easy to organize class files into packages. All you
do is put related class files in the same directory, give
the directory a name that relates to the purpose of the classes,
and add a line to the top of each class file that declares
the package name, which is the same as the directory name
where they reside.
For example, the class and other related files for the program files
from Part 2, Lesson 6: Internationalization
can be divided into three groups of files: fruit order client, view order
client, and server files. Although these three sets of classes are
related to each other, they have different functions and are to be
deployed separately.
Create the Directories
To organize the internationalization program into three
packages, you could create the following three directories
and move the listed source files into them:
- client1
- RMIEnglishApp.java
- RMIFrenchApp.java
- RMIGermanApp.java
- MessagesBundle_de_DE.properties
- MessagesBundle_en_US.properties
- MessagesBundle_fr_FR.properties
- index.html
- rmiFapp.html
- rmiGapp.html
- rmiEapp.html
- java.policy
- client2
- RMIClient2.java
- MessagesBundle_de_DE.properties
- MessagesBundle_en_US.properties
- MessagesBundle_fr_FR.properties
- java.policy
- server
- DataOrder.java
- RemoteServer.java
- Send.java
- java.policy
Declare the Packages
Each *.java
file needs a package delcaration
at the top that reflects the name of the directory. Also,
the fruit order (client1
and view order
(client2
) client class files need an
import statement for the server package because they have to
access the remote server object at runtime.
As an example, the package declaration and import
statements for the
RMIClient2.java
class file look like this:
//package declaration
package client2;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
import java.text.*;
//Import server package
import server.*;
Make Classes and Fields Accessible
With class files organized into packages, you have to declare
the server classes in the server
directory
public
so they can be instantiated by client programs,
which are created from classes in the client1
and
client2
directories.
If you do not specify public
, a class can only be
instantiated by an object created from a class in the same package.
So client programs can access the fruit order data, the fields of
the DataOrder
class have to be public
too.
The RemoteServer class and
Send interface need to be
public
classes, but their fields do not need to be public
because the do not have public data.
Fields and methods without an access specifier such as
public
can only be accessed by objects created
from classes in the same package.
Here is the new DataOrder class.
package server;
import java.io.*;
//Make class public
public class DataOrder implements Serializable{
//Make fields public
public String apples, peaches, pears, cardnum, custID;
public double icost;
public int itotal;
}
Change Client Code to Find the Properties Files
In the example, the properties files (Messages_*
) are
stored in the directories with the client source files. This makes
it easier to package and deploy the files later. So the programs can
field the properties files, you have to make one small change to the
client source code.
The code that creates the messages
variable needs
to include the directory (package name) as follows:
messages = ResourceBundle.getBundle(
"client2" +
File.separatorChar +
"MessagesBundle", currentLocale);
Compile and Run the Example
Compiling and running the example organized into packages
is a little different from compiling and running the example
in previous lessons. First, you have to execute the compiler and
interpreter commands from one directory above the package directories,
and second, you have to specify the package directories to the
compiler and interpreter commands.
Compile
These instructions assume development
occurs in the zelda
home
directory.
Unix:
cd /home/zelda/classes
javac server/Send.java
javac server/RemoteServer.java
javac client2/RMIClient2.java
javac client1/RMIFrenchApp.java
javac client1/RMIGermanApp.java
javac client1/RMIEnglishApp.java
rmic -d . server.RemoteServer
cp server/RemoteServer*.class
/home/zelda/public_html/classes
cp server/Send.class
/home/zelda/public_html/classes
cp server/DataOrder.class
/home/zelda/public_html/classes
Win32:
cd \home\zelda\classes
javac server\Send.java
javac server\RemoteServer.java
javac client2\RMIClient2.java
javac client1\RMIFrenchApp.java
javac client1\RMIGermanApp.java
javac client1\RMIEnglishApp.java
rmic -d . server.RemoteServer
copy server\RemoteServer*.class
\home\zelda\public_html\classes
copy server\Send.class
\home\zelda\public_html\classes
copy server\DataOrder.class
\home\zelda\public_html\classes
Note:
The rmic -d . server.RemoteServer
line uses server.RemoteServer
instead of
server/RemoteServer
so the _stub
and
_skel
classes are generated properly with the package.
Start rmi Registry:
Unix:
cd /home/zelda/public_html/classes
unsetenv CLASSPATH
rmiregistry &
Win32:
cd \home\zelda\public_html\classes
set CLASSPATH=
start rmiregistry
Start the Server
Unix:
cd /home/zelda/public_html/classes
java -Djava.rmi.server.codebase=
http://kq6py/~zelda/classes
-Djava.rmi.server.hostname=kq6py.eng.sun.com
-Djava.security.policy=
server/java.policy server/RemoteServer
Win32:
cd \home\zelda\public_html\classes
java -Djava.rmi.server.codebase=
file:c:\home\zelda\public_html\classes
-Djava.rmi.server.hostname=kq6py.eng.sun.com
-Djava.security.policy=
server\java.policy server\RemoteServer
Start RMIGermanApp
Here is the HTML code to load the German applet,
Note the directory/package name prefixed to
the applet class name (client1/RMIGermanApp.class
).
<HTML>
<BODY>
<APPLET CODE=client1/RMIGermanApp.class WIDTH=300 HEIGHT=300>
</APPLET>
</BODY>
</HTML>
To run the applet with appletviewer, invoke the HTML file
from the directory just above client1
as follows:
cd /home/zelda/classes
appletviewer rmiGapp.html
Start RMIClient2 in French
Unix:
cd /home/zelda/classes
java -Djava.rmi.server.codebase=
http://kq6py/~zelda/classes
-Djava.rmi.server.hostname=kq6py.eng.sun.com
-Djava.security.policy=client2/java.policy
client2/RMIClient2 kq6py.eng.sun.com fr FR
Win32:
cd \home\zelda\classes
java -Djava.rmi.server.codebase=
file:c:\home\zelda\public_html\classes
-Djava.rmi.server.hostname=kq6py.eng.sun.com
-Djava.security.policy=client2\java.policy
client2\RMIClient2 kq6py.eng.sun.com fr FR
Using JAR Files to Deploy
After testing and debugging, the best way to deploy
the two client and server files is to bundle the executables
and other related application files into three
separate JAR files, one JAR file for each client program,
and one JAR file for the server program.
JAR files use the ZIP file format to compress and pack files
into, and decompress and unpack files from, the JAR file. JAR files
make it easy to deploy programs that consist of many files.
Browsers can easily download applets bundled into JAR files, and
the download goes much more quickly than if the applet and its
related files were not bundled into a JAR file.
Server Set of Files
Here are the server files:
- RemoteServer.class
- RemoteServer_skel.class
- RemoteServer_stub.class
- Send.class
- DataOrder.class
- java.policy
Compress and Pack Server Files
To compress and pack the server files into one JAR file,
type the following command on one line. This command
is executed in the same directory with the files. If
you execute the command from a directory other than
where the files are, you have to specify the full pathname.
jar cf server.jar
RemoteServer.class
RemoteServer_skel.class
RemoteServer_stub.class
Send.class
DataOrder.class
java.policy
jar
is the jar
command. If you
type jar
with no options, you get the
following help screen. You can see from the help screen
that the cf
options to the jar
command
mean create a new
JAR file named server.jar
and put the
list of files that follows into it. The new JAR file
is placed in the current directory.
kq6py% jar
Usage: jar {ctxu}[vfm0M] [jar-file] [manifest-file]
[-C dir] files ...
Options:
-c create new archive
-t list table of contents for archive
-x extract named (or all) files from archive
-u update existing archive
-v generate verbose output on standard output
-f specify archive file name
-m include manifest information from specified
manifest file
-0 store only; use no ZIP compression
-M Do not create a manifest file for the entries
-C change to the specified directory and
include the following file
If any file is a directory then it is processed
recursively.
The manifest file name and the archive file name
needs to be specified in the same order the
'm' and 'f' flags are specified.
Example 1: to archive two class files into an
archive called classes.jar:
jar cvf classes.jar Foo.class Bar.class
Example 2: use an existing manifest file 'mymanifest'
and archive all the files in the foo/ directory
into 'classes.jar':
jar cvfm classes.jar mymanifest -C foo/ .
To deploy the server files, all you have to do is move the
server.jar
file to a publicly accessible directory
on the server where they are to execute.
Decompress and Unpack Server Files
After moving the JAR file to its final location, the
compressed and packed files need to be decompressed and
unpacked so you can start the server. The following
command means extract (x
) all files
from the server.jar
file (f
).
jar xf server.jar
Fruit Order Set of Files
The fruit order set of files (below) consists of applet classes,
web pages, translation files, and the policy file. Because they live on
the web, they need to be in a directory accessible by the
web server. The easiest way to deploy these files is to bundle
them all into a JAR file and copy them to their location.
- RMIEnglishApp.class
- RMIFrenchApp.class
- RMIGermanApp.class
- index.html (top-level web page where user chooses language)
- rmiEapp.html (second-level web page for English)
- rmiFapp.html (second-level web page for French)
- rmiGapp.html (second-level web page for German)
- MessagesBundle_de_DE.properties
- MessagesBundle_en_US.properties
- MessagesBundle_fr_FR.properties
- java.policy
Compress and Pack Files
jar cf applet.jar
RMIEnglishApp.class
RMIFrenchApp.class
RMIGermanApp.class
index.html
rmiEapp.html
rmiFapp.html
rmiGapp.html
MessagesBundle_de_DE.properties
MessagesBundle_en_US.properties
MessagesBundle_fr_FR.properties
java.policy
To deploy the fruit order client files, copy the applet.jar
file to its final location.
Decompress and Unpack Files
An applet in a JAR file can be invoked from an HTML
file without being unpacked. All you do is specify the
ARCHIVE
option to the APPLET
tag in your
web page, which tells appletviewer the name of the JAR file containing the
class file. Be sure to include the package directory when you specify the
applet class to the CODE
option.
You can leave the translation files and policy file in the JAR file.
When using appletviewer, the applet invoked from the JAR file will find
them in the JAR file.
<HTML>
<BODY>
<APPLET CODE=client1/RMIFrenchApp.class
ARCHIVE="applet.jar"
WIDTH=300
HEIGHT=300>
</APPLET>
</BODY>
</HTML>
However, you do need to unpack the web pages so you can move them to
their final location. The following command does this. Everything goes on
one line.
jar xv applet.jar index.html
rmiEapp.html
rmiFapp.html
rmiGapp.html
Note:
To run the HTML files from a browser, you need to unpack the JAR file, copy
the java.policy
file to your home directory and make sure it
has the right name (.java.policy
for Unix and
java.policy
for Windows), and install Java Plug-In.
View Order Set of Files
The view order set of files (below) consists of the application
class file and the policy file.
- RMIClient2.class
- java.policy
Compress and Pack Files
jar cf vieworder.jar RMIClient2.class java.policy
To deploy the view order client files, copy the vieworder.jar
file to its final location.
Decompress and Unpack Files
jar xf vieworder.jar
More Information
You can find more information on packages in the
Creating
and Using Packages lesson in
The Java Tutorial.
You can find more information on these and other JAR file format
topics in the
JAR File
Format trail in
The Java Tutorial.
[TOP]