23.2. WAR Files

Next, look at the WAR (web archive) example. The structure of WAR files is slightly different from the structure of ordinary JAR files. In particular, when constructing a WAR file, the src/resources directory is ignored and the src/web directory is used instead. Anything in src/web is added to the WAR file at its root, just as with src/resources for a JAR file. Other than the name, there is no difference between how these directories are used. Additionally, the src/conf directory is used to populate the WEB-INF directory in the WAR rather than the META-INF. At present, there is no way to add files to META-INF other than manually creating a META-INF directory under src/web. (The MANIFEST.MF file is created automatically by the jar task.) Another difference is that compiled classes go in WEB-INF/classes instead of at the root as with a normal JAR file.

If the abuild.war-type property in Abuild-ant.properties has the value server, we copy all JAR files in the abuild.classpath variable into the WEB-INF/lib directory. If abuild.war-type has the value client, they are copied into the root of the WAR file. Before copying the JAR files from the classpath into the WAR file, abuild places them in the abuild-java/classpath directory. If you need to create a WAR file that includes files from abuild.classpath both at the root and in the WEB-INF/lib directory, create a client WAR file and use a pre-package hook to move some of the files from classpath into src/conf/lib (remember that both of these paths are relative to the output directory, which is directory from which ant is run) so that they will end up in WEB-INF/lib. The EAR example includes a demonstration of using a pre-package hook for manipulating the contents of the classpath directory:

archive-types/war/Abuild-ant.properties

abuild.war-name = war-example.war
abuild.war-type = server
abuild.web-xml = war-example.xml

archive-types/war/Abuild.interface

# Not really a classpath item, but this is what you have to do for now.
abuild.classpath = $(ABUILD_OUTPUT_DIR)/dist/war-example.war

Here are the contents of this server WAR file:

example.war-contents.out

META-INF/
META-INF/MANIFEST.MF
WEB-INF/
WEB-INF/classes/
WEB-INF/classes/com/
WEB-INF/classes/com/example/
WEB-INF/classes/com/example/war_example/
WEB-INF/classes/com/example/war_example/WarExample.class
WEB-INF/jboss-web.xml
WEB-INF/lib/
WEB-INF/lib/har-example.har.jar
WEB-INF/lib/jar-example.jar
WEB-INF/web.xml
index.txt

The client-war example is identical except it creates a client WAR instead:

archive-types/client-war/Abuild-ant.properties

abuild.war-name = client-war-example.war
abuild.war-type = client
abuild.web-xml = war-example.xml

archive-types/client-war/Abuild.interface

# Not really a classpath item, but this is what you have to do for now.
abuild.classpath = $(ABUILD_OUTPUT_DIR)/dist/war-example.war

Here are its contents:

example.client-war-contents.out

META-INF/
META-INF/MANIFEST.MF
WEB-INF/
WEB-INF/classes/
WEB-INF/classes/com/
WEB-INF/classes/com/example/
WEB-INF/classes/com/example/war_example/
WEB-INF/classes/com/example/war_example/WarExample.class
WEB-INF/jboss-web.xml
WEB-INF/web.xml
har-example.har.jar
index.txt
jar-example.jar

In this example, the war-example build item depends on the jar-example build item which in turn depends on har-example. Notice that abuild has added har-example.har.jar to the WAR file instead of adding har-example.har. This, again, is to work around the fact that javac ignores classpath elements that are files whose names don't end with .jar or .zip. This behavior may change if it turns out to be incorrect. Another thing to observe about the WAR example is that it adds its WAR file to the abuild.classpath variable. This is another thing that may change in the future. It's not really accurate to say that the WAR file is in the classpath, but for the time being at least, this is the mechanism used for population of EAR files. Abuild will attempt to add war-example.war.jar to the classpath of build items that depend on example-war, but since this file won't exist during EAR creation (as the appending of .jar happens only during compilation), it turns out to be harmless. It's possible that an error might result if a WAR file depends on another WAR file, but there's no reason for this to ever happen. Additionally, observe that the abuild.web-xml property has to be set in the Abuild-ant.properties file in addition to the abuild.war-name property when creating WAR files.