4.4 Recording Dependencies on Server Libraries
With servlet and JSP engines (or "containers") supporting the servlet 2.2 and JSP 1.1 API, there is no portable way to designate that a Web app depends on some shared library that is not part of the servlet or JSP API itself. You have to either copy the library's JAR file into the WEB-INF/lib directory of each and every Web application, or you have to make server-specific changes that lack mechanisms for verification.
With servlet version 2.3 (JSP version 1.2), you can use the META-INF/MANI-FEST.MF file to express dependencies on shared libraries. Compliant containers are required to detect when these dependencies are unfulfilled and provide a warning. Note that although support for these dependencies is a new capability in servlet version 2.3, the actual method of expressing the dependencies is the standard one for the Java 2 Platform Standard Edition, as described at http://java.sun.com/j2se/ 1.3/docs/guide/extensions/versioning.html. Furthermore, although the method for expressing dependencies is now standardized, the way to actually implement shared libraries is nonstandard. For example, with Tomcat 4, individual class files placed in install_dir/classes and JAR files placed in install_dir/lib are made available to all Web applications. Other servers might use an entirely different approach or might completely disallow code sharing across Web applications.
Creating a Manifest File
The MANIFEST.MF file is created automatically by the jar utility. Unless you are using shared libraries, you normally ignore this file altogether. Even if you do want to customize the manifest file so that you can use shared libraries more portably, you rarely edit it directly. Instead, you typically create a text file with a subset of manifest file entries and then use the m option to tell jar to add the contents of the text file to the autogenerated manifest file. For example, suppose that you have a file called myAppdependencies.txt that is in the top-level directory of your Web application. You can create a WAR file called myApp.war by changing directory to the top-level Web application directory and then issuing the following jar command.
jar cvmf myAppDependencies.txt myApp.war *
There are two small problems with this approach, however. First, myApp-Dependencies.txt is actually part of the WAR file. This inclusion is unnecessary and may confuse the deployer who sees an unneeded file mixed in with index.jsp and other top-level Web files. Second, the WAR file itself (myApp.war) is created in the top-level directory of the Web application. It is slightly more convenient to place the WAR file one directory level up from there, so that configuration and archive files are kept distinct from the Web application contents. Both of these minor problems can be solved by use of the C option to jar, which instructs jar to change directories before adding files to the archive. You place myAppDependencies.txt one level up from the main Web application directory (myApp in the following example), change directory to the location containing myAppDependencies.txt, and issue the following jar command:
jar cvmf myAppDependencies.txt myApp.war -C myApp *
This way, the dependency file and the WAR file itself are located in the directory that contains the top-level Web application directory (myApp), not in myApp itself. Note that it is not legal to go to the parent directory of myApp and then use a directory name when specifying the files, as below.
jar cvmf myAppDependencies.txt myApp.war myApp/* // Wrong!
The reason this fails is that the name myApp incorrectly becomes part of all of the WAR entries except for MANIFEST.MF.
Contents of the Manifest File
OK, ok. So you know how to use jar to create manifest files. But what do you put in the manifest file that lets you specify dependencies on shared libraries? There are four main entries that you need, each of which consists of a single plain-text line of the form "Entry: value".
Extension-List. This entry designates one or more names of your choosing, separated by spaces. The names will be used in the rest of the manifest file to identify the library of interest. For example, suppose that several of your Web applications use JavaMail to send email. Rather than repeating the JavaMail JAR file in each and every Web application, you might use a server-specific mechanism to make it available to all Web applications. Then, your dependency file would contain a line like the following.
name-Extension-Name. This entry designates the standard name for the library of interest. You cannot choose an arbitrary name here; you must supply the name exactly as it is given in the Extension-Name entry of the JAR file that contains the actual library of interest. For most standard extensions, the package name is used as the extension name. Note that the leading name must match whatever you specified for Extension-List. So, if the standard JavaMail JAR file uses an Extension-Nameof javax.mail, the first two entries in your dependency file would look like the following.
Extension-List: javaMail javaMail-Extension-Name: javax.mail
name-Specification-Version. This entry gives the minimum required specification version of the library of interest. When the server finds an installed library, it compares the listed Specification-Versionto the minimum specified here. For example, if your Web apps require JavaMail version 1.2 or later, your dependency file might start as follows.
Extension-List: javaMail javaMail-Extension-Name: javax.mail javaMail-Specification-Version: 1.2
name-Implementation-URL. This entry lets you specify the location where the server can find the JAR file. Note, however, that it is unclear how many servers (if any) will automatically download the JAR file when necessary, rather than simply generating an error message. Combining all four entries results in a dependency file like the following.
Extension-List: javaMail javaMail-Extension-Name: javax.mail javaMail-Specification-Version: 1.2 javaMail-Implementation-URL: http://somehost.com/javaMail.jar
Although these are the four most important entries, there are a number of other possible entries. For details, see http://java.sun.com/j2se/1.3/docs/guide/extensions/ver-sioning.html. For information on JavaMail, see http://java.sun.com/products/javamail/.