views:

42

answers:

3

I'm currently migrating our build process to Maven from Ant. Our application is deployed to many different customers, each with a unique set of dependencies and and configuration. I can implement different profiles to model these and build the required wars from them. However this is a process that happens at compile time.

Each release is tagged under SVN as well as uploaded to our internal Nexus repository. I want to be able to take a defined release and reconstruct it based a profile. Is there a way to do something like this? Is there something other than profiles I should be using?

A: 

Have you taken a look at the Maven Assembly plugin?

This plugin allows you to customize how your distribution is assembled - i.e. what format (.tar.gz, .zip, etc), directory structure, etc. I think you should be able to bind several instances of the plugin to the package phase to assemble multiple variations of your output (i.e. the packaging for customer 1, customer2, etc, separately).

The deploy plugin should then automatically handle deploying each of your assembled packages in the target directory to the repository.

matt b
+1  A: 

I would take a look at your architecture and see if there is a way to split up your project into multiple projects. One would be the main code base. The other projects would depend on the JAR file produced by the main project and add in their own configuration, dependencies, etc to produce your final artifact.

This would let you version customer specific code independently of each other as well as keeping common code in one place and separate from customer specific stuff.

David
A: 

"declare several execution for the war plugin to produce several artifacts (and install/deploy them)" This sounds like this might be the way forward. How would I go about doing this?

This goes a bit against a Maven golden rule (the one main artifact per module rule) but can be done. The One artifact with multiple configurations in Maven blog post describes one way to implement this approach:

I decided to put all the environment specific configuration in a special source tree, with the following structure:

+-src/
  +-env/
    +-dev/
    +-test/
    +-prod/

Then I configured the maven-war-plugin to have three different executions (the default plus two extra), one for each environment, producing three different war files: beer-1.0-dev.war, beer-1.0-test.war and beer-1.0-prod.war. Each of these configurations used the standard output files from the project and then copied the content from the corresponding src/env/ directory on to the output files, enabling an override file to be placed in the corresponding src/env/ directory. It also supported copying a full tree structure into the output directory. Thus if you for instance wanted to replace the web.xml in test you simply created the following directory:

src/env/test/WEB-INF/

and placed your test specific web.xml in this directory and if you wanted to override a db.property file placed in the classpath root directory for the test environment you created the following directory:

src/env/test/WEB-INF/classes

and placed your test specific db.property file in this directory.

I kept the src/main directory configured for development environment. The reason for this was to be able to use the maven-jetty-plugin without any extra configuration. Configuration

Below you find the maven-war-plugin configuration that I used to accomplish this:

<plugin>
  <artifactId>maven-war-plugin</artifactId>
  <configuration>
    <classifier>prod</classifier>
    <webappDirectory>${project.build.directory}/${project.build.finalName}-prod</webappDirectory>
    <webResources>
      <resource>
        <directory>src/env/prod</directory>
      </resource>
    </webResources>
  </configuration>
  <executions>
    <execution>
      <id>package-test</id>
      <phase>package</phase>
      <configuration>
        <classifier>test</classifier>
        <webappDirectory>${project.build.directory}/${project.build.finalName}-test</webappDirectory>
        <webResources>
          <resource>
            <directory>src/env/test</directory>
          </resource>
        </webResources>
      </configuration>
      <goals>
        <goal>war</goal>
      </goals>
    </execution>
    <execution>
      <id>package-dev</id>
      <phase>package</phase>
      <configuration>
        <classifier>dev</classifier>
        <webappDirectory>${project.build.directory}/${project.build.finalName}-dev</webappDirectory>
        <webResources>
          <resource>
            <directory>src/env/dev</directory>
          </resource>
        </webResources>
      </configuration>
      <goals>
        <goal>war</goal>
      </goals>
    </execution>
  </executions>
</plugin>

(...) I can define each customer project with profiles but I don't know if there's a way to release them to a repository.

You have several options:

  • use profiles and run the build several times (create artifacts with a classifier and install/deploy them)
  • declare several execution for the war plugin to produce several artifacts (and install/deploy them)
  • use different modules (and maybe war overlays to merge a common part with a specific one)

Or at least a way in Maven to automatically build an artifact with a specified profile from say an SVN tag.

Well, this is doable. But without more details about a particular problem, it's hard to be more precise.

Pascal Thivent
"declare several execution for the war plugin to produce several artifacts (and install/deploy them)" This sounds like this might be the way forward. How would I go about doing this?
samblake