Creating a common web module using Maven

Working with two different web-apps, with a common source base, often very similar web functionality and sometimes the need to have common sources made me hunt down how this could be done. As we are using Maven for project management, researching this ended up in war overlays. This is a nice Maven feature and in fact very simple to implement. Keep reading to see how I implemented overlays..


I created a new common-web module starting in the root pom.

<dependencyManagement>

<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>common-web</artifactId>
<version>${project.version}</version>
<classifier>classes</classifier>
</dependency>

<!– Then in the pom for common-web, packaging needs to be set to war –>
<packaging>war</packaging>

<!– Finally add dependency to the module in the web apps, one for the jar, and one to overlay the war –>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>common-web</artifactId>
<version>${project.version}</version>
<classifier>classes</classifier>
</dependency>

<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>common-web</artifactId>
<version>${project.version}</version>
<type>war</type>
<scope>runtime</scope>
</dependency>

Using this brilliant Maven method, the files in your common-web module are now overlayed (copied) to your web app.
But wait, this does not work without specifying a maven-war-plugin.

<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-beta-1</version>
<configuration>
<attachClasses>true</attachClasses>
<webResources>
<resource>
<directory>${basedir}/src/main/webapp</directory>
</resource>
<resource>
<directory>${basedir}/src/main/webapp/WEB-INF</directory>
<targetPath>WEB-INF</targetPath>
</resource>
</webResources>
<packagingExcludes>
**/applicationContext-common-web.xml
</packagingExcludes>
</configuration>
</plugin>
</plugins>

As you can see, it's possible to exclude sources. And since I am using Spring, I needed to exclude the spring context file. The reason for this is simple, you don't want to load your context twice. If you happen to not load your context files from the classpath you can remove this exclusion.

Note the maven-war-plugin version. I've used version 2.1-beta-1 which supports exclusion from packaging.

======================================================

A couple of bugs were found in the above example. I wanted to use this module not just for war overlay, but also a common module for classes. This was not handled by the setup i posted earlier. The solution to this problem was:

<!– In the common-web module, this has to change –>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<attachClasses>true</attachClasses> <!– This line is needed to generate a jar file to use as a dependency in other modules –>

<!– Then in the module you want to use this dependency –>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>common-web</artifactId>
<version>${project.version}</version>
<classifier>classes</classifier> <!– This is needed because the jar file generated using attachClasses is prefixed default with -classes.jar –>
</dependency>

Thats it, keep enjoying the war overlays!




just use the maven-war-plugin…it does what's called overlays:
http://maven.apache.org/plugins/maven-war-plugin/overlays.html

Pickett, Andrew
np
in short, if you have
<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.1.1</version>
in your pom, and then include a WAR as a dependency, it will overlay that war ontop of yours…
you can then configure it to exclude files, or include specific ones, etc…etc…