views:

1515

answers:

5

I have ten WAR files, all of which have nearly identical code and markup. The only differences lie in the images, CSS and Messages. I hit on the concept of Profiles but I haven't quite groked it yet and I'm not sure if this can handle what I need it to do.

Basically, I want a base project with different profiles for the 10 different WARs. Whenever a build is started with a given profile, it goes to a repository (either local or my organization's) and retrieves the CSS, images and messages files and places them in the correct spot before finishing out the process. I can't imagine this is much different than going out and retrieving a JAR file and putting it in WEB-INF lib.

I'm sure this isn't TOO far out in left field and I want to stick to Maven's sweet spot as much as possible. Any help would be appreciated!

A: 

Profiles should be a good fit for this. According to the information at the maven build profile docs this shouldn't work. Specifically, they say

build as specified inside of a profile is not a full implementation of the traditional
build POM element. This build is really another class in the model - from which the POM
build is derived - and only allows the plugins and pluginManagement subelements when 
defined here. This sidesteps any issues with secondary validation after the pom.xml is 
parsed in this case.

But I just tested it and it included the appropriate resources by including a build element with a resources definition inside.

In your pom, you will want to include a profile for each of your webapps. For instance, in my test, I did the following:

<profile>
    <id>abc</id>
    <activation>
        <activeByDefault>false</activeByDefault>
    </activation>
    <build>
        <resources>
            <resource>
                <directory>abc</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
        </resources>
    </build>
</profile>
<profile>
    <id>xyz</id>
    <activation>
        <activeByDefault>false</activeByDefault>
    </activation>
    <build>
        <resources>
            <resource>
                <directory>xyz</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
        </resources>
    </build>
</profile>

Then, I had a a directory abc containing a file abc.properties, and another xyz with a corresponding xyz.properties file.

For all shared resources, you would have a element that also has a element that includes all those that you want to be used in every webapp.

Finally, when you build you would specify the profile of the webapp you would like to build, such as mvn -P abc clean install

One BIG issue you may have with this approach is that each artifact built will have the same name, and one will overwrite the other in your local repository.

digitaljoel
A: 

Yes, I'm answering this question twice because each approach is significantly different.

Rather than have a single pom.xml that has a profile for each of your war files, you could have a project that contains 11 modules. One maven module that has all of the shared source, and then each of your war files would be another, adjacent module that only has the files specific to it. All of these modules would be under one root pom.

In the pom for each of your war modules, you would then setup the resources and sourceDirectory within your build configuration to point to ../base-project/src/main/resources and ../base-project/src/main/java respectively.

The maven-war-plugin configuration would then have webResources setup to point to ../base-project/src/main/webapp AND to your war specific resources in ./src/main/webapp.

With this solution, you would have different maven artifacts for each of your war files and they could all co-exist within your .m2 repository without any issues.

digitaljoel
+1  A: 

I can think of solutions based on profiles, the maven war plugin and filtering as described in Adding and Filtering External Web Resources.

But this doesn't answer the how to use web resources as "dependencies" part of your question.

For this, the How to share resources across projects in Maven blog post describes something very close and might help.

Pascal Thivent
I saw successful in packing some XML files using the blog post you referenced. The trick is creating a separate profile to package the CSS, etc. and storing it into your repository.
Mike Cornell
+2  A: 

If you want to keep each of the projects separate, you can give each project its own pom.xml. In each child project pom, add a dependency for the parent project. This will cause the build to do an "overlay" in which files from the child project are added to (or overwrite files in the) parent project. Example dependency for child project:

<dependency>
   <groupId>com.example.app</groupId>
   <artifactId>example</artifactId>
   <version>1.0.0</version>
   <type>war</type>
</dependency>
jt
Why was this voted down? I tried this one (since it was so simple) and it worked but still evaluating the other options.
Drew
A: 

You could always use the maven-remote-resources-plugin. You would create submodule builds for each of your resource sets, say creating one called 'my-project-resources-customer1.jar. These are just like any other maven artifact and can be put in your local or remote repos.

In your war build you would have the plugin config shown below which will explode the contents of the specified resource bundle jars to your target directory and subsequently include them in your war file. This config could be eaily controlled by profiles that set a property 'profilename' to select the required resource.

<plugin>
    <artifactId>maven-remote-resources-plugin</artifactId>
    <executions>
      <execution>
        <phase>validate</phase>
        <goals>
          <goal>process</goal>
        </goals>
        <configuration>
          <resourceBundles>
            <resourceBundle>org.mygroup:my-project-resources-${profilename}:${pom.version}</resourceBundle>
          </resourceBundles>
        </configuration>
      </execution>
    </executions>
  </plugin>

One caveat (its a small one) is to be careful how you specify the resource versions if you're using the the maven release plugin. If your resources and war file share a common version, you'll want to use the ${pom.version} property in the plugin. Then when the release plugin updates your parent version to 1.1 the plugin will reflect this automatically use the 1.1 version of the resource bundle. If you're not releasing the resource bundles in lockstep with the war then you'll be fine specifying the version explicitly.

HTH

ste

sgargan