Activating a default Maven profile defined in settings.xml with other profiles in the pom.xml


In Apache Maven, there are different places to configure profiles:

  • The project pom.xml
  • The user’s settings.xml
  • The installations settings.xml

I wanted every developer to be able to customise the build properties independently of the pom.xml. It is a very bad practice to have everyone modifying the pom.xml locally. One would also argue that it is a very bad practice to have developers customise build properties. That’s a debate for another time šŸ™‚

The profiles that we have are:

  • Development (default)
  • Jenkins (continuous integration)
  • Test
  • Acceptance
  • Production

The profiles define the target environment for the build.

At first, I tried to define a profile as activeByDefault in the settings.xml file while setting the other profiles in the pom.xml not active by default. That did not work at all because in this case the profile defined in the settings.xml is active at any time and overrides other profiles.

The solution that I found was to use a property to activate a profile. The profile defined in the settings.xml is the Development profile. It would be activated by the absence of such a property. Indeed, it would be boring to have to specify a property for most of the builds.

The settings.xml looks like this:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
	  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
			      http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <profiles>
    <profile>
      <id>Development</id>
      <activation>
	<property>
	  <name>!env</name><!-- The exclamation mark indicates that the property shall be absent -->
	</property>
      </activation>
      <properties>
	<target.environment>Development</target.environment>
	...
      </properties>
    </profile>
  </profiles>
</settings>

When using the Maven command mvn help:active-profiles, it yields:

The following profiles are active:

 - Development (source: settings.xml)

The development profile is active if the property env is not set using the Maven command line parameter -Denv=xxx.

All the other profiles are defined in the pom.xml:

...
  <profiles>
    <profile>
      <id>Jenkins</id>
      <activation>
	<property>
	  <name>env</name>
	  <value>Jenkins</value> <!-- This is the value for that property that will activate the profile -->
	</property>
      </activation>
      <properties>
	<target.environment>ContinuousIntegration</target.environment>
	...
      </properties>
    </profile>
    <profile>
      <id>Test</id>
      <activation>
	<property>
	  <name>env</name>
	  <value>Test</value>
	</property>
      </activation>
      <properties>
	<target.environment>Test</target.environment>
	...
      </properties>
    </profile>
    <profile>
      <id>Acceptance</id>
      <activation>
	<property>
	  <name>env</name>
	  <value>Acceptance</value>
	</property>
      </activation>
      <properties>
	<target.environment>Acceptance</target.environment>
	...
      </properties>
    </profile>
    <profile>
      <id>Production</id>
      <activation>
	<property>
	  <name>env</name>
	  <value>Jenkins</value>
	</property>
      </activation>
      <properties>
	<target.environment>Production</target.environment>
	...
      </properties>
    </profile>
...

To activate any profile from the pom.xml instead of the Development profile, we just have to pass the env property to the command line. For example:

$ mvn -Denv=Test help:active-profiles

The command above yields the following result:

The following profiles are active:

 - Test (source: pom)

Ignoring Eclipse and Maven files and Folders with Git


The file .gitignore tells Git which files to ignore at commit time. The ignore file itself shall be added and committed to the repository.

Add the following lines to in order to ignore Eclipse project files and folders

.classpath
.project
.settings/

Add the following line to ignore Maven target folder:

target

Bash-Fu: Replacing text in multiple files with one Perl command


When I posted Ā Bash-Fu: Replacing text in multiple files in oneĀ line, I knew that there would be a simpler way to achieve that. Thanks to my former colleague Ben, here is an even simpler way that uses a perl command.

$ perl -p -i -e 's/0.6-SNAPSHOT/0.7-SNAPSHOT/g' `find ./ -name pom.xml`

This command replaces the occurences of 0.6-SNAPSHOT with 0.7-SNAPSHOT in all the pom.xml files in the current directory and sub-directories. It is the usage of the find command that provides the list of files to process to the perl command.

Pay attention to the ` that surround the find command. These are not quotes but accents.

Telling Subversion to Ignore Files and Directories from the Command Line


To tell Subversion to ignore files and directories, it is necessary to set the value of the svn:ignore property. To do so, open a terminal.

Run the following command in the terminal. It will open a Nano window in the terminal to allow editing the files and folders to ignore.

svn propedit svn:ignore .

In my case, I wanted to ignore Maven and Eclipse files. I therefore added the following directories:

  • target
  • .classpath
  • .project
  • .settings

To make the changes effective, you must commit your changes:

svn commit

Bash-Fu: Replacing text in multiple files in one line


We use Maven on our project for the build. The hitch is that when we want to change version numbers after each iteration, we need to do it by hand. I think I’m missing something with regard to Maven functionality or plug-ins but that’s for another post.

I wanted to replace the version for the iteration in all modules in one single command line. Here it is:

find . -name "pom.xml" -print0 | xargs -0 grep -lr -e '0.5-SNAPSHOT' | xargs sed -i 's/0.5-SNAPSHOT/0.6-SNAPSHOT/g'

The chain of commands is comprised of three parts:

  1. Find all the pom files and print the files (print0) for the next command
  2. Grep the required text and print the file names (-l) instead of the test for the next command
  3. Replace all occurences of the text text in each file

I’m sure there a better ways to do it with both Bash and Maven. Nevertheless, this is pretty handy.

A minimal Maven pom.xml to start with


When one create a default Maven application using an archetype, it is rather incomplete by default. The following pom was created usingĀ maven-archetype-quickstart:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>shz</groupId>
  <artifactId>foo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>foo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

I need to more start with. Indeed, it is necessary to configure a few more things in order to start developing. In this post, I will look at a minimal pom.xml project file for a jar.

Setting the dependencies

I most of the time use JUnit and Mockito to unit test my code, therefore, I add the following dependencies to the pom.xml:

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-all</artifactId>
      <version>1.8.5</version>
      <scope>test</scope>
    </dependency>
</dependencies>

Working around theĀ maven-eclipse-plugin bug

I develop in Eclipse. If I don’t specify which version of the maven-eclipse-plugin to use, I run into the following error:

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building aagile 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-eclipse-plugin:2.8:eclipse (default-cli) @ aagile >>>
[INFO]
[INFO] <<< maven-eclipse-plugin:2.8:eclipse (default-cli) @ aagile <<<
[INFO]
[INFO] --- maven-eclipse-plugin:2.8:eclipse (default-cli) @ aagile ---
[INFO] Using Eclipse Workspace: null
[INFO] Adding default classpath container: org.eclipse.jdt.launching.JRE_CONTAINER
[INFO] Resource directory's path matches an existing source directory. Resources will be merged with the source directory src/main/java
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.387s
[INFO] Finished at: Sat Nov 20 20:55:45 CET 2010
[INFO] Final Memory: 10M/309M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-eclipse-plugin:2.8:eclipse (default-cli) on project aagile: Request to merge when 'filtering' is not identical. Original=source src/main/java: output=null, include=[**/*.java], exclude=[], test=false, filtering=false, merging with=resource src/main/java: output=target/classes, include=[**/*.xml|**/*.properties], exclude=[**/*.java], test=false, filtering=true -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

To fix it, I simply fix the version of the plugin to use as follows:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-eclipse-plugin</artifactId>
      <version>2.6</version>
      <configuration>
        <ajdtVersion>1.6</ajdtVersion>
      </configuration>
    </plugin>
  </plugins>
</build>

Specify the target version of Java

I want to compile my project against Java 6 so that I can use the features of the language. I do that by specifying the target in the maven-compiler-plugin:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>2.3.1</version>
      <configuration>
        <source>1.6</source>
        <target>1.6</target>
      </configuration>
    </plugin>
  </plugins>
</build>

The final pom.xml looks like

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>shz</groupId>
  <artifactId>foo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-all</artifactId>
      <version>1.8.5</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-eclipse-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <ajdtVersion>1.6</ajdtVersion>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

References

%d bloggers like this: