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 som开发者_JAVA百科ething like this? Is there something other than profiles I should be using?
"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 correspondingsrc/env/
directory. It also supported copying a full tree structure into the output directory. Thus if you for instance wanted to replace theweb.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 adb.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. ConfigurationBelow 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.
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.
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.
I ended up doing something slightly different. We're not storing the releases in our internal repository. Instead we're building using Hudson and a multi-configuration project (one configuration/profile for each customer). This way when a release is made the Hudson job is run to build different wars for all customers. They are then stored on the Hudson server instead of Nexus. Builds for specific versions and customers can also be built at any time from the releases in Nexus. – samblake Mar 16 '11 at 12:32
精彩评论