Thomas Sundberg

May 21, 2014

Use Maven build directory in your plugin

This post has been migrated to

How can you get the build directory in your maven plugin?

The answer to this question may seem simple, just refer to ./target in your plugin and everything should work. This works in the simple case. It does, however, not work when you are using you plugin in a multi module project. Your plugin will not know where it is executed and cannot refer to a subdirectory relative to the directory where Maven is invoked. It may be executed in a multi module build or a single module.

The directory . will refer to the execution directory and therefore will ./target refer to a target directory in the execution directory. This is not where the target directory lives in a multi module project. The target directory will typically be ./moduleName/target. Maven have the build directory, it is stored in the property ${}. So far so good, but how do you access this property from the Java code you are writing your plugin in? It turns out that you can specify a parameter, with any name you wish, and set its default value to ${}. The example below will log the build directory to the console when it is executed.


package se.thinkcode; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.logging.Log; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; /** * Will log the absolute path to the target directory in the execution log */ @Mojo(name = "get-build-dir", defaultPhase = LifecyclePhase.VALIDATE) public class BuildDirMojo extends AbstractMojo { @Parameter(defaultValue = "${}") private String projectBuildDir; @Override public void execute() { Log log = getLog();"");"Project build dir: " + projectBuildDir);""); } }

When Maven populates the parameter projectBuildDir, it will expand the expression ${} to the actual value. This may be very reasonable if your background is shell scripting. As a developer I found the syntax a bit strange. There is no apparent reason why a String that should contain a default value is expanded into something else. If I set something to default then I expect to see that value when I look at it later, given that I haven’t changed the value.

The implication of this is that if you need access to any Maven property in your plugin, just define a parameter and set its default value to the property you need.

If you are new to Maven plugin development, there are a few things that could be worth mentioning.

I subclass an AbstractMojo that will give me access to a Maven logger.

I am using two specific Maven annotations to define some metadata about the plugin.

First I define that this class should be a Mojo. A Mojo is the Maven equality to a a Pojo, Plain Old Java Object. Mojo stands for “Maven plain Old Java Object”. Using the Mojo annotation I define that this plugin should be called using the goal “get-build-dir” from another Maven project. Using the same annotation, I define that the default execution phase should be validate. An example is defined later.

Second, I define a parameter that this Mojo should use. This parameter will be populated by Maven before the execution of the goal. In this case, it will be populated by expanding the default value defined into the current build directory using a Maven property.

The last part of this class is defining a method that will be executed. It is called execute and will be called when the goal get-build-dir is called.

To be able to build the example above, I used the pom below:


<?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>4.0.0</modelVersion> <groupId></groupId> <artifactId>parameter-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> <packaging>maven-plugin</packaging> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-plugin-plugin</artifactId> <version>3.2</version> <configuration> <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound> </configuration> <executions> <execution> <id>mojo-descriptor</id> <phase>process-classes</phase> <goals> <goal>descriptor</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-plugin-api</artifactId> <version>3.2.1</version> </dependency> <dependency> <groupId>org.apache.maven.plugin-tools</groupId> <artifactId>maven-plugin-annotations</artifactId> <version>3.2</version> </dependency> </dependencies> </project>

I define that the packaging type should be maven-plugin. I also define that the maven-plugin-plugin should be used. It will help me to package the plugin and expand the annotations used above to something Maven can interpret and use. I also need two dependencies to get access to the AbstractMojo and the annotations.

To test the plugin, I defined a pom like the one below and call it using:
mvn validate


<?xml version="1.0" encoding="UTF-8"?> <project xmlns="" xmlns:xsi="" xsi:schemaLocation=""> <modelVersion>4.0.0</modelVersion> <groupId></groupId> <artifactId>test-plugin</artifactId> <version>1.0-SNAPSHOT</version> <build> <plugins> <plugin> <groupId></groupId> <artifactId>parameter-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> <executions> <execution> <goals> <goal>get-build-dir</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>

You should now be able to get any Maven property into your plugin and be able to expand the Maven functionality with a Maven plugin when you find a need for it.

Think of one thing before you start writing you own plugin,though. There may be a Maven way to do things that you should use instead. It is probably easier and many of the habits Maven try to enforce onto your project are actually really good.


Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at

%d bloggers like this: