Page 2 of 4
While it is possible to perform these procedures on a class level, over time the process can become a bit of an administrative nightmare. In a large system, the problems presented in the introduction are often particularly evident.
In Java, the next higher level of granularity from the class is the package. Following a general definition of a component
as a service abstraction provided by a collection of cooperating classes, the Java package fits quite nicely. Packages tend
to be made up of logically related classes and interfaces, such as the core APIs java.io, java.math, java.net, and so on. And from an administrative point, a system assembled from packages is significantly more manageable than one
made up of independent classes.
Going back to the problems identified in the introduction, Sun's specification points out that packages also conform to the notion of a contract. They expose a public part, which forms the contract, and they have a private part, the implementation. An implementation can consist of private, protected, and "default access" classes, methods, and attributes that are hidden from the client. Other than behavioral variations, changes made to an implementation won't affect the contract exposed by a package.
So, while the Java package can be used to specify the contract, how do we associate it with the component information, such as the vendor's name, the component name, and its version?
One commonly employed approach is Javadoc. There is a standard template for documenting Java packages, including sections on what specifications the package implements and so on. Unfortunately, Javadoc isn't always installed. If you've deployed a production J2EE system, did you install Javadoc on all of the hosts in the cluster? Or if you added a new host to an existing cluster, did you install the Javadoc on that one as well? While useful during development, Javadoc depends on a user's ability to make the association between a physical package and its documentation. Is this something we should rely on in a system with many components distributed across a network of hosts?
Another approach is to hardcode this type of information into each class, maybe even providing public methods to retrieve it. Most of us realize the drawbacks of duplicating information and logic and the problems that result from doing so. Alternatively, we can code the information into a class implementing the Singleton pattern. This works fine, but not all packages have a singleton object, or are suited to have one.
One could argue for and against each of these approaches in different scenarios. A situation we should ideally avoid is having different vendors document their component information in different ways. This is bound to confuse and irritate users.
The Java Product Versioning Specification approach for documenting this type of information is based on the jar file. Stored
within every jar file is a plain text file called Manifest.mf. By default, the jar tool automatically generates this file and places it in a directory called meta-inf. In its default form, the manifest file created by the jar tool contains two fields, a mandatory Manifest-version attribute and another called Created-by that the jar tool automatically generates. It usually looks something like: