What is a WAR overlay?def: Overlays are used to share common resources across multiple web applications. The dependencies of a WAR project are collected in WEB-INF/lib, except for WAR artifacts which are overlayed on to the WAR project itself. http://maven.apache.org/plugins/maven-war-plugin/overlays.html
How do you solve code duplication using WAR Overlays?One approach to reducing the amount of duplicated code is to create a separate maven project with the packaging target type of WAR. Then in each of your application's pom.xml file, include the overlay project as a dependency and construct it as an overlay using the maven-war-plugin. This is known as a Fat WAR Overlay. (NOTE: In the next post I will cover other types of WAR overlays to help mitigate transient dependency problems)
More specifics please!First, let's create a new maven WAR project and name it "branded-templates". (NOTE: This post is not intended to be a comprehensive guide on creating a maven project, only adding to an already working maven project. If you need more assistance, please refer to some of my other post or maven's website for more guidance.)
In our new branded-templates application, we will need to fill this with our resources. Here is my recommended locations to place web-related resources within your project:
- /src/main/webapp/styles – used to hold your CSS files, (example: brand.css, reset.css, etc)
- /src/main/webapp/images/ – used to hold brand-wide images, (example: company-logo.png, facebook-icon.png, company-background.jpg, etc)
Naming for now will not be important, but you will have to make decisions here because you have two naming options here that will have development implications. You can name your resources and/or folders the same in both of your applications or you can name them different to get different desired results. How is this going to impact my design and why do you need to think about this? (Answer coming after we add to the containing webapp project, keep following!)
Let's continue. We can now install your branded-templates WAR overlay to your local maven repository:
mvn clean install
If all is good, you should see a "Successful build" along with a 1.0-SNAPSHOT for your WAR's version.
Next, let's crate a new main application called "main-webapp". If you have an existing webapp, feel free to use that and work along with this example. Inside of the main-webapp's pom.xml file, we need to add a plugin to build the two WARs into one WAR and add the overlay as a dependency to the project.
Add to your dependencies section:
<dependency> <groupId>com.yourcompany</groupId> <artifactId>branded-templates</artifactId> <type>war</type> </dependency>
Note that we are adding this as a WAR type, do not leave the type blank.
Add to your plugins section:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.1.1</version> <configuration> <overlays> <overlay> <groupId>com.yourcompany</groupId> <artifactId>branded-templates</artifactId> </overlay> </overlays> </configuration> </plugin>
Next, we've added the war-plugin which will take our application and build a WAR. If you're familiar with maven's artifact types, you'll already know that your project builds a WAR already, so why the plugin? The plugin is where the "magic" of the overlay happens. This is where the overlay is placed into the main-webapp's WAR file.
How many WAR files will I have?When using a WAR overlay, you will start with two or more WAR files (presumably one or more overlays and a main-webapp), but will ultimately end up with one WAR artifact (your main-webapp) in which to deploy to your environment. Though it is completely possible to run your overlay as a standalone application, I recommended you read my next post (coming soon) on dependency management within overlay projects to avoid dependency problems in your main-webapp project.
So what happens when there is a conflicting resource?As you can imagine, there can be conflicts between overlay's resource names and the main project's resources. This is what I asked you to think about from the question posed above. If you have the same location and named file in your overlay application as you do in your main application, the overlay version will be ignored for the main application's version. This can work for or against you, so think about how you might use both. How would you want to leverage the customization abilities in the main webapp.
Note, if you plan on utilizing Sitemesh decorators, it's not a bad idea to put your decorators.xml and sitemesh.xml file in your WEB-INF folder and the corresponding JSPs in the WEB-INF folder (suggest placing them in /WEB-INF/decorators folder). Remember to add the sitemesh web.xml information into your containing main-webapp's web.xml!
One more gotcha that might arise out of this would be dealing with the web.xml. The overlay's web.xml file is NOT copied over nor is it merged in any way, so if your overlay has specific web.xml file information you can either manually add it to the web.xml or use a <include file="/WEB-INF/web-overlay.xml"> tag where you've added the contents to a file named web-overlay.xml to the overlay war project.
Tips for rapid developmentAt this point you should have an overlay and a working master webapp leveraging that WAR overlay. Since you have your resources in the overlay and you are probably working in your main-webapp, and it is probably becoming a pain to keep deploying a new version of your overlay project, you can simply refer to the SNAPSHOT version of your overlay inside your main-webapp pom.xml file and do a local install of your overlay.
Leaving notesFollow my blog and get the next blog post dealing with dependency management with overlays.
Feel free to leave comments or questions and I'll do my best to get back to you in a reasonable time frame. I would like to thank Dynacron Group (my consulting firm) for allowing me some time to work on this blog post!