Building a WAR

Let's build the Java Petstore waf-web WAR project that we've introduced in Figure 2. WAF stands for Web Application Framework and it's the equivalent of Struts. WAF is a blueprint recommendation from Sun. When we convert the Java Petstore Ant build into a Maven one, we divide the WAF project into several dependent subprojects (Figure 7):

Figure 7. WAF Maven subprojects

The waf-controller-ejb subproject is an EJB state machine (it's the extension of the MVC pattern on the server side). The interesting part is that it generates an EJB JAR and an EJB client JAR on which we need to depend on for the waf-web WAR. The other subprojects simply generate standard JARs.

Let's have a closer look at the waf-web directory structure (Figure 8):

As you can see, we have located the WAR's web files (JSPs, images, HTML pages, etc) in the src/main/webapp directory. This follows our strategy of putting all the sources that make the main artifact in src/main. The web.xml files goes in src/main/webapp/WEB-INF along with whatever other files you may want to put there (Taglib definitions, etc). Note that for the sake of clarity we've filtered out lots of JSPs and XML files in Figure 8. There are normally more than what you can see, but that doesn't affect our build exercise.

In the case of this waf-web project we have no java source files. If you had any you would put them in src/main/java and define that location in your project.xml, as explained earlier. The java classes will then find their way automatically to the WAR's WEB- INF/classes directory. We'll show this in the section about building a WAR with XDoclet below.

We're going to use the Maven plugin WAR to build our WAR. We need to configure it to tell it that the WAR's web files are located in src/main/webapp. This is done in the project.properties file:

maven.war.src = ${maven.src.dir}/main/webapp

Note: You may wonder why the WAR plugin is not configured by default to look into the recommended place. The reason is historical. In the early days the recommended location for sources was src/java (without the main/part) and thus all plugins have been configured to look there for their files. Thus, for example, the WAR plugin looks for its web files in src/webapp. The reason it hasn't been changed is simply to preserve compatibility. Changing the default will break hundreds, if not thousands, of users who are using the default location. However this is now changed in Maven2.

Let's have a look at the project.xml file. The only special part is the <dependencies> section. Not only does it list the artifacts the waf-web project depends on, it also tells the Maven WAR plugin what artifacts to include in the WAR's WEB-INF/lib directory:

Every time we want to tell the WAR plugin to include a specific dependency in the WAR, we tag it using:

<properties>
<war.bundle>true</war.bundle>
</properties>

Notice also the use of the ejb-client type in the dependency on the waf-controller-ejb above. This is the way to tell Maven that we want to depend on the ejb-client jar and not on the main ejb-jar (which we would depend on by specifying an "ejb" type instead of "ejb-client").

Last, as we're lazy (Remember that a lazy programmer is a good programmer!) we specify, as usual, the default goal to run using the <defaultGoal> element. This means that we can now simply type "maven" and the war:install goal is executed:

The Maven WAR plugin has several other properties that can be configured. You can, for example, choose to generate the web.xml file by your own means and tell the plugin. This is done by creating a pregoal on war:war in which you do the generation and then set the maven.war.webxml property to point to the generated file. Those other more exotic settings are explained in the plugin's reference documentation.