2009-11-23

Maven: adding profile-dependent resources to project

Recently I needed to use different .properties files in my project depending on whether it runs in IDE at my workstation or is packed as .war file and deployed on production server. Project uses Maven to build itself. I've made some notes about solving this problem which hopefully will help somebody to do something similar.

Profiles can be configured in pom.xml file and then activated either from command line (using -P key)
or by some condition - operating system, environment variables, enabled by default etc.
Notice that few profiles can be activated at the same time (in my application this feature isn't used, but it was the reason why I didn't enable some profile by default).
Profiles can define plugins, properties, modules, resources and lot of other things which are enabled only for specific profile. But in this post we will need only resources settings. Detailed information about maven profiles available in Maven: The Definitive Guide and at Apache Maven Site.

So, suppose we have 3 different directories with main (meaning non-test) resources in our Maven-controlled project:
  • our_project/src/main/resources - common resources
  • our_project/src/main/resources_development - resources only for development version
  • our_project/src/main/resources_production - resources only for production version
Such resources may be .properties-files with data source or logger configuration or something like that. Files from resources directory (for all profiles) and files either from resources_development or resources_production (depending on selected profile) should be placed to resulting web-archive (.war), and, while making their way to archive, to our_project/target/classes (for example, from here Eclipse IDE deploys resource files to local Tomcat) and to our_project/target/our_war_file_name/WEB-INF/classes (our_war_file_name actually replaced by configured name of resulting .WAR file, from here Maven builds .WAR file).

In order to achieve this profiles may be configured this way in pom.xml file:



production



${basedir}/src/main/resources_production


${basedir}/src/main/resources





develop



${basedir}/src/main/resources_development


${basedir}/src/main/resources





This code defines 2 profiles - "production" and "develop". Notice that profile-specific directory goes first - profile-specific resources will be copied first, and if common resources directory contains same files they will NOT be owerwritten.


How these profiles can be used: type mvn clean package -Pproduction to build .WAR file for production environment or mvn clean package -Pproduction to build .WAR file for development environment. Similar options may be configured in Eclipse "Run Configurations" dialogue. Note that if you run production build in your IDE then IDE may deploy production-specific resources on your development environment, so you will need to build development version to get things back. Goal "clean" for our case is really neede only if you build for one profile, and then build for another profile in the same directory - then some resouces may remain from previous profile. If you always build for the same profile in one directory "clean" can be skiped if you want to speed up build.

If you need more advanced resource manipulation you can see options of Maven resource plugin. Its basic configuration in pom.xml looks like this:




maven-resources-plugin
2.4.1

..some configuration...



..execution-specific settings. For example, some settings may be applied to different
phases.




Hopefully, it will help somebody :)

No comments: