The Java Specialists' Newsletter [Issue 026] - Package Versioning
Author: Herman Lintvelt
JDK version:
Category: Language
You can subscribe from our home page:
http://www.javaspecialists.co.za (which also hosts all previous issues,
available free of charge
Welcome to the 26th issue of "The Java(tm) Specialists' Newsletter". My
silence these past two weeks was due to having my hands full moving my outlook
contacts list to the new mailserver. Yes, it has finally happened! In addition,
I've done some cosmetic changes to the
archive of newsletters
and as you can see, the newsletter is now sent out in HTML format with syntax
highlighted code. I want to thank
Peter Carruthers for
letting me use some ideas from his newsletter for this new format.
I am very grateful to fellow Java guru
Herman Lintvelt for authoring
this week's newsletter. He is the only person I know who understands the
javax.swing.JTree, perhaps I should call him Dr. Swing. In case you need some
serious Java GUI development done, please send him an email, or if you have GUI
code written by amateurs that needs to be cleaned up.
Herman did his Bachelor of Science Degree in Computer Science in 1998 at
"University" of Stellenbosch, and since then has worked almost exclusively in
Java, especially using Swing and JDBC, with bits of JAI and JMF. After only 2
years as sucker^H^H^H^H^H^Hemployee, he decided it's not for him and recently
started Polymorph Systems to enter the "freelance contractor" market.
Please remember to forward this newsletter to as many Java enthusiasts as you
know who might be interested in receiving such a newsletter. Special thanks to
the person who sent the last newsletter to their local JUG, it caused about 30
subscriptions .
And now for Herman's first newsletter...
Package Versioning
While having a (rare) bit of idle time in this coldest, wettest winter of
probably the last decade down here at the Southern tip of Africa, I thought it
might be good to write about package versioning. Talking of wettest, I live on a
wine-farm near Stellenbosch, and were it not for my trusty old '76 Jeep, I would
have been cut off from civilization last week, as the dirt road was turned into
a muddy river, but this is not a 4x4 newsletter, so back to Java(tm)...
Versioning of packages is a very good discipline to follow. Yes, if you have
source-control package like SourceSafe, CVS, Clearcase, etc, you can (probably)
be rest assured that you can keep track of your sourcecode versions. But what
happens if your jar-files are finally (after months of intensive testing by
expert testers distributed to the client and the totally unexpected
happens: a bug shows up! You need to be able to determine whether the client had
an old version of the package, as the newest version definitely fixed all the
remaining bugs.
I like simple things (that's why this newsletter is not complex), and with
package versioning it must be the same: it must be easy and fast to keep the
package version information up to date (else I will be too tempted to ignore the
versioning process). In a project I worked on previously, we added a class to
each java package which implemented the same interface and returned the major,
minor, patch and build numbers as hard-coded strings. Added to this was a
"PackageVersionInterrogator" class that would then get these strings from all
the packages when the debug logger required them. This had a few disadvantages:
- the debug logger had to know all the packages for which it had to get
the package versions (thus any packages from where a class might *possibly*
be loaded, would have to be included in the list of known packages for the
debug logger)
- if the Java app could not even start up, then the client could not
browse the jar-file for versioning information, as the version info was
contained in class files.
But Alas!!, once again our friends at Sun had a lot of foresight. A while
back I "discovered" the existence of the java.lang.Package class,
and what's more: this class contains all kinds of nice accessor methods for
versioning information! How do you use it? Easy, for every jar file in your
project (where every jar file can contain one or more java packages), you need
to create your own manifest.mf file (or whatever name you give to
it), and invoke the option of the jar-tool to use this manifest file.
Let's look at how this manifest file will look. Suppose we have some classes
in a package called com.worldsgreatestApps.java.media and some in a
package called com.worldsgreatestApps.java.media.ui. When we run
the jar-tool to create a jar-file for these classes, we use the following
manifest.mf file (which will be put in the META-INF subdir inside the
jar file):
Manifest-Version: 1.0
Main-Class: jmftest.PackageTest
Specification-Title: Java Media Framework
Specification-Version: 2.0
Specification-Vendor: Sun
Name: com/worldsgreatestApps/java/media/
Implementation-Title: WorldsGreatestApps Super Media Framework
Implementation-Version: 1.0.2
Implementation-Vendor: Polymorph Systems
Name: com/worldsgreatestApps/java/media/ui
Specification-Title: Java Media Framework
Specification-Version: 2.0
Specification-Vendor: Sun
Implementation-Title: WorldsGreatestApps Super Media Framework UI classes
Implementation-Version: 1.1.1
Implementation-Vendor: Polymorph Systems
Some observations:
Main-Class is not part of this versioning, it indicates the
main class to run in the jar file, and thus enables you to "run" this jar
file directly by using java -jar jarfilename.jar.
Specification-[Title/Version/Vendor] specifies information
about the specification implemented inside the package(s)
Implementation-[Title/Version/Vendor] specifies information
about the specific implementation contained in the package.
Name (and the empty line in front of it) specifies the name
of a package, and must preceed the section for every package in the manifest
file. Thus all packages in the jar-file for which we need versioning info
(should be all the packages) will have a section in the manifest file.
- Both the
Specification and Implementation
entries can be specified in the "general" section of the manifest file (like
the first Specification entries in the example), and these
entries will then be used to describe packages that do not have specific
entries in the manifest file.
- The
X-Version entry values are -by convention- in
the form of major.minor.micro(/patch), but it can basically be any
descriptive string.
- The last line of the manifest file should be ended with a newline, else
the last line will not be read in probably by the classloader.
How do I use this information in my java code? Well, if the class loader
finds package information like this for the package that a class belongs to, it
will create a java.lang.Package object for that class, which you
can get a handle to by calling on your
classinstance.getClass().getPackage(). This object has some methods to
get all the info specified in the manifest file.
If no information is specified for a specific package, the classloader first
looks to see if there is a "general section" for the version information (i.e.
Specification and Implementation entries at the top of
the file, before the first empty line). If it is there, it will use this info to
populate the Package object; else it will create a Package object
that will return null on the version-info method calls.
What's the advantages of using this method to do your package versioning?
Well, it's simple and easy to use. Your debug logger can use the standard
Java(tm) API to get package version information, and can get a handle on all the
loaded packages by calling Package.getPackages(), for example:
/** simple class to list all loaded packages with */
public class PackageLister {
//...
public static void listPackages() {
Package[] allPackages = Package.getPackages();
System.out.println("All loaded packages:");
for(int i=0; i < allPackages.length; i++) {
System.out.println("" + (i+1) +
": " + allPackages[i].getName() +
": " + allPackages[i].getImplementationTitle() +
", version: " + allPackages[i].getImplementationVersion());
}
}
//...
}
Another big advantage: on the client site it's easy to open the jar file and
view the manifest file manually if (by some operating system or network error of
course) your application won't even start up enough to produce debug output.
I hope this inspired those *few* of you who are not using package versioning
techniques to start doing it, and those who are using overly complex techniques
or tools, to simplify. I'm very interested to know what versioning "systems" are
being used out there, so please feel free to email me at
herman@javaspecialists.co.za with your ideas and descriptions of the systems
you are using for versioning your projects.
Vriendelike groete
Herman
Copyright 2000-2004 Maximum Solutions, South Africa
Reprint Rights. Copyright subsists in all the material included
in this email, but you may freely share the entire email with anyone you feel
may be interested, and you may reprint excerpts both online and offline provided
that you acknowledge the source as follows: This material from The Java(tm)
Specialists' Newsletter by Maximum Solutions (South Africa). Please contact
Maximum Solutions for more
information.
Java and Sun are trademarks or registered trademarks of Sun Microsystems,
Inc. in the United States and other countries. Maximum Solutions is independent
of Sun Microsystems, Inc.
7063 bytes more | 1 comment | | Score: 0
|