This week's book giveaway is in the OCPJP forum. We're giving away four copies of OCA/OCP Java SE 7 Programmer I & II Study Guide and have Kathy Sierra & Bert Bates on-line! See this thread for details.
The problem is that all three .war files include the archiveX.jar files in their WEB-INF/lib directory as well. So there are 3 copies of each .jar (sometimes more) in the .ear.
I'm fixing the build.xml files so that the .war applications will share the .jar files at the top level of the .ear file and eliminiate the .jars from each WEB-INF/lib. I've modified each .war file to include a Class-Path: in its Manifest.mf so that they all use the .jar files at the top of the .ear file:
The .war applications find the classes they need so the Class-Path: setting works as far as sharing common .jar files among multiple .war applications.
There's a new problem, however. The applications need to load some .properties files that are in the WEB-INF/classes directories of the respective .war files. Inside webapp2.war, for example, these .properties files are in
The old application (no Class-Path: entry in Manifest.mf and the .jar files in WEB-INF/lib) was able to load these .properties files from WEB-INF/classes. After putting the Class-Path: in the Manifest.mf so that the top level .jar files are used the .war applications can't load .properties files from WEB-INF/classes.
It appears that putting a Class-Path: in the Manifest.mf of a .war drops the WEB-INF/classes directory from the .war classpath in JBoss 4.0.3.
I've solved this by putting the .properties files in the top level of the .ear file, but I don't understand why I have to do this.
Here's how the code loads the .properties files works.
The files to be loaded are prefixed with a '/' like "/WebServices.properties". The loading is done by a shared utility class in one of the shared top level .jar files. It creates a FileInputStream like this:
is = this.getClass().getResourceAsStream(fileName);
The javadocs for Class.getResourceAsStream() say:
"The rules for searching resources associated with a given class are implemented by the defining class loader of the class. This method delegates to this object's class loader."
So maybe the issue isn't with with the Class-Path: dropping WEB-INF/lib from the class loader's classpath.
I believe that JBoss uses one class loader to load the top level .jar files and different class loaders for the .war applications. I'm speculating that when code in a .war calls a method in a class in one of the top level .jar files the relevant class loader is the one that loaded the top level .jar file and not the one that loaded the .war file (which would include WEB-INF/lib in its classpath).
The JBoss docs are, uh, in flux at the moment so they haven't been much use.
The way i used to manage a similar application on JBoss-4.0.x was to place those jars at the top level of the EAR and make an entry for them in the application.xml (as a java module):
This way the archiveX.jar is available to all the components in the EAR which includes those war files. You don't have to add the archiveX.jar entries in the MANIFEST.MF of the WAR files.
I do agree that if the number of such common archiveN.jar keep increasing then the application.xml becomes ugly.
However, starting JBoss-4.2.x there's a very clean and easy way to manage this. You can create a folder named lib at the root of the EAR and place all your common jars (which are required by various components in the EAR) in this lib folder. JBoss will by default add all these jars to the classpath of the application and make them available to all the components in the EAR. You don't have to do anything with the application.xml nor the MANIFEST.MF in the war. If upgrading to JBoss-4.2.x is an option for you, then i would recommend you use the latest stable 4.2.2 GA version.