The term deploy describes the process of installing the pieces of an application to a host and making whatever modifications are required to the host environment so the application runs correctly without further modifications. A patch is a group of Java class files, one or more documentation files, and one or more batch files that installs them to modify the behavior of a deployed program.
Deploying a Java application, particularly a distributed Java application, is a complex task, since applications typically require installing a number of jar files and batch files (sometimes to different locations) as well as making changes in the host's environment. Most developers create a custom install program to simplify deployment. (Usually the developer employs a deployment program builder like InstallAnywhere to create the program.)
Generating the install program is time consuming, and it must be tested and verified before it and its related application can be shipped to customers. This is a particularly slow process if the install procedure must work on many platforms (Linux, Mac, Unix, Windows, etc.).
The cost and time required to create and test an install program become significant obstacles to the timely delivery of upgrades and bug fixes. However, minor upgrades and simple bug fixes for a single platform can be quickly implemented with a patch. (Note: Patching other platforms usually requires only minor modifications to the patch batch file.)
Patches take advantage of a Java feature called the classpath, a list of locations where the Java launcher (Java.exe) searches for Java class files. The launcher searches the first location, then the second, and so on. If a suitable class is found, the launcher stops searching. If none is found, a "No Class Found" error message is generated. When the application is deployed, if the developer is wise enough to consider the possibility of needing a patch, the first location is empty, the jar files are deployed to the second, third, and so on, locations. When stand-alone class files for a patch are placed in the first search location, they take precedence over the class files deployed in jar files in that location and over stand-alone class files and class files deployed in JAR files in all following locations, effectively replacing them.
The classpath is a string. In Unix colons separate search locations. In Windows semicolons separate them. A location is either a directory location or a jar file (including path) location. One special piece of terminology for defining locations: a dot indicates "the directory where the batch file that calls the launcher was started."
A typical classpath in Windows looks like this:
In other words, search the directory where the batch file that called the launcher was started, then the directory C:\MyClasses, then the jar file C:\MyOtherClasses\SomeJar.jar. Note: When searching locations, the launcher searches for a fully qualified class file (package plus a dot plus class name) and uses the package name as a directory hierarchy.
Given the above classpath, if the launcher was searching for someRootPackage.someSubPackage.ThisClass, it would search for the file ThisClass.class in the directory someSubPackage under someRootPackage:
Note: If the launcher finds a candidate, the last thing it does is verify that the file found does indeed contain a suitable package statement.
- under the directory where the batch file was started
- if it wasn't there, under the directory C:\MyClasses
- if it wasn't there, in the file C:\My OtherClasses\SomeJar.jar
- if it wasn't there, the "No Class Found" error is generated
Setting the Classpath
There are three ways to set the classpath. A classpath environment variable can be defined at system start-up or in the batch file that calls the Java launcher. Neither is recommended if multiple Java applications requiring different classpaths are installed. The recommended way to define the classpath is to use the Java Launcher command line option -cp in the batch file that starts the launcher.
The -cp option allows the developer to specify a classpath that's valid for the Java launcher until it terminates. Consider this Unix command line:
java -cp .:A.jar:B.jar com.myPackage.MyClass
A class file in B.jar is effectively erased by placing another version of the same class in A.jar, and a class file in either B.jar or A.jar is effectively erased by placing another version in the current directory. A.jar and B.jar can be patched by placing *.class files in the current directory. Removing the patch simply requires removing the *.class files.
- The launcher searches in the current directory (the ".") for classes.
- If it doesn't find the class, it searches in A.jar.
- If it doesn't find the class in either the current directory or in A.jar, it searches in B.jar.
Note: If java.exe is started without the -cp command line and if no classpath environment variable is specified, only the default location of the libraries is searched. (The default location is the lib directory under the same directory as the bin directory where java.exe is stored.)
Warning: A classpath variable containing many search paths significantly increases search time!
The procedure outlined in this example assumes the developer is using Windows NT for a development platform with a Zip program installed and is deploying to a Sun Unix platform. However, the general procedure is platform independent.
Suppose you need to patch the jar file SomeJarFile.jar in the directory/home/ myname/someproduct by replacing the file com.somePackage.MyClass.class with the file J:\MyClasses\com\some Package\MyClass.class. Also, suppose the program in the jar file is started by a batch file in the same directory as the jar file using the line:
java -cp SomeJarFile.jar com.somePackage.SomeClass
First, assign a meaningful name to the patch, say patch2000082301. (The algorithm "patch" + year + month + date + patch number guarantees that an alphabetical listing of patch names is also a listing from oldest to newest, which simplifies patch management.)
Second, create a directory with the same name as the patch, say, J:\patch2000082301, to store the patch and working files associated with it.
A Zip File
Third, use a Zip program to create a Zip file with the same name as the patch, say, patch2000082301.zip.
A Readme File
Fourth, use a text editor to create a "readme" text file with a meaningful name, say, readme2000082301.txt. The file should contain a description of the patch and a list of the files included in it. For example:
readme2000082301.txt describes the patch patch2000082301.
This patch is implemented by unjaring patch2000082301.zip
into the directory containing the jar file SomeJarFile.jar
To install this patch, copy patch2000082301.zip
into the directory containing the jar file SomeJarFile.jar
and unjar it with the following line:
jar -xvf patch2000082301.zip
To remove this patch, go to the directory that contains the jar file SomeJarFile.jar and run removePatch2000082301.ksh.
This patch consists of three files:
readme2000082301.txt - a description of the patch
com.somePackage.MyClass.class - the "fixed" class
removePatch2000082301.ksh - the patch remover
Add this file to the Zip file. Don't add any location information for this file!
Map a Drive to the Appropriate Root Directory
Fifth, map a drive, say, K: to J:\MyClasses. (If the J: drive is a Unix drive, use the "ln" command). If mapping a new drive to the folder is too difficult, copy com and its subdirectories to the root of some drive. Mapping the drive creates the correct path for the class files in the Zip file.
Add the Class File to the Zip File
Sixth, use the Zip program to add K:\com\somePackage\MyClass.class to the Zip file. Be sure the Zip file shows the location com\somePackage for the file. (WinZip is one program that does this.)
Add a Remove Batch File
Seventh, using a text editor, write a batch file with a meaningful name that removes the class files, say, remove- Patch2000082301.ksh. The file needs to contain only the lines:
echo batch file to remove patch patch2000082301
echo must be in the same directory as the jar file being patched.
Add this file to the Zip file.
The batch file must not contain any ^M characters at the end of a line or they'll be treated as part of the file name and the RM command will not work correctly. Since this file is inside a Zip, the "transfer binary" ftp option won't strip out the ^Ms.
Copy the Zip File
Eighth, copy the Zip file to the directory where the jar file is deployed.
Modify the Start File
Ninth, using VI or some other editor, modify the batch file that starts the program so it reads:
java -cp .:SomeJarFile.jar com.somePackage.SomeClass
This change forces the loader to first search for new class files under the directory where the jar file is deployed before it searches the jar file. (Hopefully, this change has already been made.)
Unjar the Zip File
Tenth, at the command line in the directory where the jar file is deployed, unjar the Zip file:
jar -xvf patch2000082301.zip
Restart the Program
Last, the program being patched must be terminated if it's currently running. When restarted by the modified batch file, the new class files should be loaded so testing and verification can begin. If testing isn't successful, you can remove the patch using the batch file removePatch2000082301.ksh. If it's successful, you can claim a great victory and announce that the patch is deployed.
A Possible Problem
Caution: If a previous patch involving MyClass.class is already installed, this procedure will destroy the old patch class file. To avoid this possibility, rename the old MyClass.class file something like MyClass.class.oldpatch before you unzip the new patch file. (Saving this file is a good idea; you may find that the new patch doesn't work correctly, so you'll want the old file available.)
John R. Hines, P.E., is
president of Software
Consulting Engineer, Inc., in Dallas, Texas. He develops distributed Java
applications during the day and teaches Java
programming at Richland College at night. He's an enterprise architecture consultant for a
large-scale project using Java and CORBA at
MCI Worldcom. [email protected]
Chris White is a software development manager for MCI Worldcom. He has delivered several
large-scale projects using Java, CORBA, and XML technology over the
past 10 years. [email protected]