Wednesday, February 26, 2014

Maven Profiles - per module

Maven Profiles

Activation per module

One of the hardest parts of maven, in my opinion, for someone coming from a programing background, is that the flow of maven is not a method call.
In a lot of cases we would like to create a batch process (group of plugins) that do something, and then invoke them in different modules. So what you would expect to do is to create a profile with all the plugins that you want, and then to active it on a module level.
For instance a simple example is to download all dependencies of the project to the target directory. In this case we will define the profile in the parent pom as follows:
<profile>
  <id>trace</id>
  <build>
    <plugins>
          <plugin>
               <artifactId>maven-dependency-plugin</artifactId>
               <groupId>org.apache.maven.plugins</groupId>
               <executions>
                 <execution>
                       <phase>package</phase>
                       <goals>
                         <goal>copy-dependencies</goal>
                       </goals>
                       <configuration>
                         <outputDirectory>${project.build.directory}/lib</outputDirectory>
                       </configuration>
                 </execution>
               </executions>
          </plugin>
         </plugins>
  </build>
</profile>

Now the problem is that when I invoke this profile it will be active on all modules. In this case it might be nice, but what if I have multiple modules and want to invoke the profile from only some of the modules.
This is where profile activation comes in. There is an option to activate a profile based on a system parameter like:
  <profile>
    <activation>
      <property>
        <name>debug</name>
      </property>
    </activation>
  </profile>

This will activate the profile if the system property of “debug” exists. Of course you can also add the option to check the value of the parameter:
  <profile>
    <activation>
      <property>
        <name>environment</name>
        <value>test</value>
      </property>
    </activation>
    ...
  </profile>

What is missing is that this feature only works with system parameters and not maven parameters. So you cannot set a parameter per module with a different value, and have maven evaluate it.
Another issue that you must always remember: when running maven, maven will compile the pom and create an effective pom (you can run mvn “effective-pom” to view it) and then run it. This means that you cannot do any manipulation during runtime that will affect the run of maven.

Solution – files

The solution that I found to run profiles per module is the use of file activation. Let’s say that I have some test modules. Sometimes I want to run a tomcat before running the tests and others not (just junit). In the standard way I will need to create a “tomcat” profile in each pom, and copy all the code that configures and deploys the pom.
I want to write the profile once in the parent pom, and then activate it only in those modules that need it. To do this I create the profile in the parent pom, and add the following activation:
<profile>
        <id>tomcat</id>
        <activation>
               <file>
                       <exists>profile.tomcat.active</exists>
               </file>
        </activation>                  
        ...
</profile>
 
Now for each module that I want to activate this profile, I need to have the file profile.tomcat.active in the pom directory. This will activate the profile, and the file needs to be there before you run the maven command, so you cannot copy it during the maven run.

This can also be used in a Jenkins scenario, where in the Jenkins job before running the maven, you add the files or delete them and the run the maven via Jenkins.

No comments:

Post a Comment