Multi brand (skinned) application with Maven 2 and Wicket (take 1)
In this two parts article, I will explain how to configure a web application built with Maven to support "branding", or skinning. That is, support different distribution skinned with particular images, logo, background, text. In the end we just want to keep separated the static contents and choose the right set when we package our application so that the result is a war with just the content for a single company. I call this a branded distribution using brand as a similar word for skinning. Brand looks more enterprise and general than skinning, anyway :)
In the second part of the article I will also cover the Wicket side of the story. The Maven side works by himself, anyway. Some thoughts, before to start.Fundamentals stuff, but important to remember: files that are in the war root are accessible from an HTML file with a relative path, so if we can have an image under myapp.war/images/pic.png we can acess it with src="images/pic.png".Instead, when we need to load an image or a text file from Java code, it must be in the Classpath, so it had to be under myapp.war/WEB-INF/
Fundamentals, I told.Another thing: we want to develop in comfort under our IDE, spcifically Eclipse, not being doomed to perform a Maven compile every time to filter some property. Test should run with their own resources, build path in Eclipse should be consistent and not be affected by multi brand configuration so that Eclipse copy modified resources on the fly and we have latest version in place without going to ask Maven again. Last thing: as always, use what already exists. Wicket has a built-in support for skinning (called styling) and Maven provides "profiles". Let's use everything we can. Ready, go!Maven Side - Profiles Let's first introduce the concept that we are running our application in a particular mode, a brand mode, whatever. Comes natural to define a maven property in pom.xml
<properties> ..... <brand>stage</brand> </properties>Where "brand" is the name of the property and "stage" is the value. For those not familiar with Maven properties, let's say just this: in every file that will be processed by maven during a build session, maven will "filter" all the variables and they will be substituted by the value defined in pom. In a few words: ${brand} --> stagein every file filtered by Maven. Included pom.xml itself. So we will have different brands: stage is my word for "demonstration application". We can have companyA, companyB, and so on. To implement different brands, in maven, we use maven profiles. While stage is a top level POM property, we now define:
<profiles> <profile> <id>companyA</id> <properties> <brand>companyA</brand> </properties> </profile> </profiles>As we all know, to activate a profile we add "-P companyA" in the maven command line and all the profile configuration will override the default ones. So now we have a default brand, stage, and a companyA specific profile. Maven Side - ResourcesIn my stage brand I have to use free images, a personal disclaimer and avoid all contents owned by my customer. So I create a folder "brands" with a sub folder for each "brand" [1]. So in "src/main/brands/stage" I put my free to use contents.
To let maven choose the folder accordingly to the chosen brand, we configure the new resource this way:
<resources>
<resource>
<filtering>false</filtering>
<directory>src/main/brands/${brand}/</directory>
<includes>
<include>**/*.txt</include>
</includes>
</resource>
...
</resources>
In my particular situation, I am interested in having just *.txt files under my Classpath. Please note that I have also put every file in the brand folder under a sub folder I call "contents", so I do not have a mess of files in the root of my war. Here is how I load resources from java:
getClass().getClassLoader().getResourceAsStream("contents/" + "myResource.txt")
Now let's deal with static images, typically some logo, background and so on. Target is to access images from HTML file simply with an img tag and a src="contents/header.jpg"
We need to configure what in maven are called "web resources", and deal with the maven-war-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>src/main/brands/${brand}/</directory>
<includes>
<include>**/*.jpg</include>
<include>**/*.gif</include>
<include>**/*.png</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
In the end, the "src/main/brands/${brand}" folder is just a new folder threated as maven normally threat "src/main/webapp" where we normally found the css folder and other folders with static content. This is the reason I normally keep files under "src/main/brands/${brand}/contents", to keep war root clean.
To summer up, here is the folder layout:
src/main/ - brands - stage - contents/disclaimer.txt - companyA - contents/disclaimer.txt - webapp -css
This completes the maven side of the problem. In the next article we will attack the "web" side, with Wicket, and finish with fixing the development environment.

