Do Maven project properties have write-once semantics - maven

I observed a Maven behavior today that left me puzzled. Either the project properties have some sort of write-once semantics or... I failed to find any reference documentation that would explain this behavior.
Can I dynamically set Maven properties in the validate phase to have them evaluated as plugin properties in later phases?
Goal
I want to skip the execution of a plugin in a profile based on the existence of some other property.
Plan
Run the Groovy plugin in the validate phase.
Evaluate the existence of that other property.
Set the skip project property.
Use the skip property for the configuration of plugins that run in later phases.
POM excerpt
<profile>
<id>my-id</id>
<activation>
<file>
<exists>${basedir}/somefile</exists>
</file>
</activation>
<properties>
<skipIt>false</skipIt> <!-- intention: use this as default value -->
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<scripts>
<script>
<![CDATA[
def someOtherProp = project.properties['some-other-property']
def skipIt = someOtherProp ? 'false' : 'true'
project.properties['skipIt'] = skipIt
println skipIt
println project.properties['skipIt']
]]>
</script>
</scripts>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<configuration>
<skip>${skipIt}</skip>
</configuration>
<executions>
<execution>
<id>my-unpack</id>
<phase>process-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
Behavior
If some-other-property does not exist (i.e. is not set) this prints true twice. That means the Groovy evaluation is correct and skipIt was correctly set. Yet, the dependency-plugin still runs the my-unpack execution. Why?
However, if I remove <skipIt>false</skipIt> on line 9 everything works as I expect. Why?

Related

Using sonar.test.exclusions with Sonarqube 6.3

I'm currently evaluating Sonarqube 6.3 (a big upgrade from my current 5.5 instance) and I'm getting confused trying to work out the functionality of the sonar.test.exclusions setting.
There's this question: Sonar Maven Plugin: How do I exclude test source directories? which seems to indicate that it is used to exclude test files from analysis (which is what I'm after - I don't want my sonar ruleset run over my unit tests). The documentation https://docs.sonarqube.org/display/SONAR/Narrowing+the+Focus also indicates that it is used to 'exclude unit test files' (perhaps this can be expanded upon to make it clearer?)
Thing is, when I add sonar.test.exclusions with a value of **/src/test/** and then run my analysis, I'm still getting code smells and the like being found for:
Foo/src/test/java/foo/bar/BarTest.java
Foo/src/test/java/lah/LahTest.java
etc.
When I use sonar.exclusions instead, they don't show up. Why is sonar.test.exclusions not doing what I expect?
First of all: if you have a Maven project, you should use the scanner for Maven (mvn sonar:sonar). It will simplify your configuration, and will automatically register src/test/java folder as a test directory.
Now if you want to do the configuration manually, or understand what is going on under the hood, here is the explanation: SonarQube scanner work with 2 sets of files, main and test. Main source files are configured using the property sonar.sources. Test source files are configured using sonar.tests.
On top of that, you can filter some content using the sonar.[test.]exclusions properties.
In you case your problem is that Foo/src/test/java/foo/bar/BarTest.java seems to be considered as a main source file. That's why sonar.test.exclusions has no effect.
Using maven with verfication goal (mvn clean verify sonar:sonar install), I have used this configuration without problems:
...
<properties>
....
<sonar.exclusions>
**/generated/**/*,
**/model/**/*
</sonar.exclusions>
<sonar.test.exclusions>
src/test/**/*
</sonar.test.exclusions>
....
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
<sonar.coverage.exclusions>
**/generated/**/*,
**/model/**/*
</sonar.coverage.exclusions>
<jacoco.version>0.7.5.201505241946</jacoco.version>
....
</properties>
....
Coverage exclusion configuration, inside properties (up) and jacoco plugin configuracion:
.....
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>target/jacoco.exec</dataFile>
<outputDirectory>target/jacoco-ut</outputDirectory>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
....

Cannot use jacoco JVM args and surefire JVM args together in maven

I am using maven with the jacoco plugin to generate code coverage metrics. I am having some difficulty in configuring the surefire plugin with the java options required by the jacoco plugin. I've seen some answers about this already on Stack Overflow but something is not working for me.
I have a multi-module project, and one of my modules configures the surefire plugin as follows:
foo/pom.xml:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-XX:MaxPermSize=512m</argLine>
</configuration>
</plugin>
</plugins>
This works as expected.
Now I want to incorporate jacoco to get code coverage metrics, so I added a CodeCoverage profile that handles all the jacoco configuration:
parent/pom.xml:
<profile>
<id>CodeCoverage</id>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals><goal>prepare-agent</goal></goals>
<configuration>
<propertyName>surefire.argLine</propertyName>
</configuration>
...
</execution>
<executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
It is seen here that if the CodeCoverage profile is specified, then the jacoco plugin is configured to use the surefire.argLine property, and that property is used to configure the argLine for the surefire plugin.
I then updated the pom.xml file for the foo module to use the surefire.argLine property generated by the jacoco plugin:
foo/pom.xml:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>${surefire.argLine} -XX:MaxPermSize=512m</argLine>
</configuration>
</plugin>
</plugins>
This approach is specified in the jacoco plugin documentation (see [1]).
When I build the foo module with the CodeCoverage profile, I see the following:
[foo] $ mvn clean install -X -PCodeCoverage
...
[INFO] --- jacoco-maven-plugin:0.7.0.201403182114:prepare-agent (jacoco-initialize) # foo ---
[INFO] surefire.argLine set to -javaagent:...\\org.jacoco.agent\\0.7.0.201403182114\\org.jacoco.agent-0.7.0.201403182114-runtime.jar=destfile=...\foo\\\target\\coverage-reports\\jacoco-ut.exec
...
[DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-surefire-plugin:2.13:test' with basic configurator -->
[DEBUG] (s) argLine = -javaagent:...\\org.jacoco.agent\\0.7.0.201403182114\\org.jacoco.agent-0.7.0.201403182114-runtime.jar=destfile=...\\foo\\target\\coverage-reports\\jacoco-ut.exec -XX:MaxPermSize=512m
...
[INFO] --- jacoco-maven-plugin:0.7.0.201403182114:report (jacoco-site) # foo ---
[INFO] Analyzed bundle 'Foo' with 59 classes`
So the jacoco plugin is executed, a surefire.argLine property is created, the argLine for the surefire plugin uses the surefire.argLine property and the local MaxPermSize argument, and a target\code-coverage\jacoc-ut-exec file is generated, as expected.
However, if I do not use the CodeCoverage profile, then I get an error, because the ${surefire.argLine} property (used in foo/pom.xml) is not created by the jacoco plugin, and is not defined anywhere:
[foo] $ mvn clean install -X
...
[DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-surefire-plugin:2.13:test' with basic configurator -->
[DEBUG] (s) argLine = ${surefire.argLine} -XX:MaxPermSize=512m
...
Error: Could not find or load main class ${surefire.argLine}`
Sinec the jacoco plugin was not invoked, there's no surefire.argLine property created, hence the error.
So, I go back to the parent/pom.xml and create this property, with no initial value:
parent/pom.xml:
<properties>
<surefire.argLine></surefire.argLine>
</properties>
Now when I build the foo module without using the CodeCoverage profile, I get no errors:
[foo] $ mvn clean install -X
...
[DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-surefire-plugin:2.13:test' with basic configurator -->
[DEBUG] (s) argLine = -XX:MaxPermSize=512m
...
[INFO] BUILD SUCCESS`
The surefire argline is now correct (using the empty surefire.argLine property) and there is no target\code-coverage directory, as expected.
So now I go back to generating code metrics, using the CodeCoverage profile:
[foo] $ mvn clean install -X -PCodeCoverage
...
[INFO] --- jacoco-maven-plugin:0.7.0.201403182114:prepare-agent (jacoco-initialize) # foo ---
[INFO] surefire.argLine set to -javaagent:...\\org.jacoco.agent\\0.7.0.201403182114\\org.jacoco.agent-0.7.0.201403182114-runtime.jar=destfile=...\\foo\\target\\coverage-reports\\jacoco-ut.exec
...
[DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-surefire-plugin:2.13:test' with basic configurator -->
[DEBUG] (s) argLine = -XX:MaxPermSize=512m
...
[INFO] --- jacoco-maven-plugin:0.7.0.201403182114:report (jacoco-site) # foo ---
[INFO] Skipping JaCoCo execution due to missing execution data file:...\foo\target\coverage-reports\jacoco-ut.exec
It can be observed here that the jacoco plugin is invoked and sets the surefire.argLine property, but the surefire.argLine property with the empty value defined in the parent/pom.xml file is actually used to create the argline for the surefire plugin.
As a result, there is no jacoco-ut.exec file, and no target\code-coverage directory, when I use the CodeCoverage profile.
I'm not sure what I am doing wrong here. I'm declaring an argLine property as suggested by the jacoco documentation, and using it whenever a surefire plugin needs to specify additional argument. Other answers on Stack Overflow suggest creating a property with the same name as the jacoco argLine property to handle the case when jacoco is not invoked.
Any suggestions?
edit
Maybe one solution is to explicitly declare the surefire.argLine property in the CodeCoverage profile, and forget about using the argLine of the jacoco plugin:
<profile>
<id>CodeCoverage</id>
<properties>
<surefire.argLine>-javaagent:${jacoco.agent.jar}=destfile=${jacoco.report.path}</surefire.argLine>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<!-- no longer specifying 'argLine' for jacoco plugin ... -->
</execution>
<executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- ... instead the arg line is configured explicitly for surefire plugin. -->
<argLine>${surefire.argLine}</argLine>
</configuration>
</plugin>
</plugins>
</plugin>
</build>
This will create the surefire.argLine property to use the java agent required by the jacoco plugin, and configure the surefire plugin to use that property for its JVM args. The jacoco plugin will now create a argLine property, but this will be ignored. It's not an elegant solution (since I'm making assumptions about how the jacoco plugin works, and this may change in a future version).
edit
The jacoco.agent.jar property must also be set, by pointing to its location in the local repository (not sure if this is robust) or by using the dependency plugin to copy the jacoco agent jar to the local build directory:
<profile>
<id>CodeCoverage</id>
<properties>
<jacoco.agent.jar>${project.build.directory}/jacoco-agent.jar</jacoco.agent.jar>
...
</project>
<build>
...
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>download-jacoco-agent</id>
<phase>process-test-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.agent</artifactId>
<version>${jacoco.version}</version>
<classifier>runtime</classifier>
<outputDirectory>${project.build.directory}</outputDirectory>
<destFileName>jacoco-agent.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
edit
Not sure if using the dependency plugin is the right approach, or pointing to the jacoco agent artifact in the local repository:
<profile>
<id>CodeCoverage</id>
<properties>
<jacoco.agent.jar>${settings.localRepository}/org/jacoco/org.jacoco.agent/${jacoco.version}/org.jacoco.agent-${jacoco.version}-runtime.jar</jacoco.agent.jar>
</properties>
...
</profile>
This is simpler, and does not require copying an artifact to the local build directory, but is fragile: changes in the repository layout will break this.
[1] http://www.eclemma.org/jacoco/trunk/doc/prepare-agent-mojo.html
Try using
#{argLine}
instead of
${argLine}
(or surefire.argLine in your case)
It allows surefire to read a property as modified by other plugins instead of reading the one substituted by Maven itself. Then you can set the argLine param to empty in Maven properties:
<properties>
<argLine></argLine>
</properties>
Which now will not cause any problems. More here: How do I use properties set by other plugins in argLine?
Since the jacoco-maven-plugin:prepare-agent goal executes before the maven-surefire-plugin, try adding the ${argLine} variable into the argLine value set by the maven-surefire-plugin.
Example:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.1</version>
<configuration>
<argLine>-server -ea -XX:MaxPermSize=256m -Xmx4g -XX:-UseSplitVerifier ${argLine}</argLine>
</configuration>
</plugin>
I had the same problem and this solution worked for me, without any need to reconfigure other sections of the POM.
If your project already uses the argLine to configure the surefire-maven-plugin, be sure that argLine defined as a property, rather than as part of the plugin configuration. For example:
<properties>
<argLine>-your -extra -arguments</argLine>
</properties>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Do not define argLine here! -->
</configuration>
</plugin>
Resulting coverage information is collected during execution and by default written to a file when the process terminates.
Worked for me. See: http://www.eclemma.org/jacoco/trunk/doc/prepare-agent-mojo.html
Try adding the argLine property in the properties section (as shown in the code below) instead of adding it in the configuration section of maven-sure-fire plugin. Jacoco maven plugin will just append to this and things will work as expected.
<properties>
<argLine>-XX:MaxPermSize=512m</argLine>
</properties>
See https://docs.sonarqube.org/display/PLUG/Usage+of+JaCoCo+with+Java+Plugin
My solution is to use multiple profiles.
The first profile sets a blank value for the surefire.argLine and the failsafe.argLine and is active by default.
<profile>
<id>not-sonar</id>
<properties>
<surefire.argLine/>
<failsafe.argLine/>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
The second profile has the jacoco plugin configuration and is inactive by default.
<profile>
<id>sonar</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin-version}</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<propertyName>surefire.argLine</propertyName>
</configuration>
</execution>
<execution>
<id>default-prepare-agent-integration</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<propertyName>failsafe.argLine</propertyName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
When you activate the sonar profile the not-sonar profile will automatically be turned off.
This should be a little more elegant than using other plugins to do the work for you. You can now use the ${surefire.argLine} variable in your argLine and it will always exists and be set when you run your build.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>${surefire.argLine} -XX:MaxPermSize=512m</argLine>
</configuration>
</plugin>
If you still have problems because the ${surefire.argLine} does not have a value you can also set a dummy property like so:
<profile>
<id>not-sonar</id>
<properties>
<surefire.argLine>-DdummyProperty=notUsed</surefire.argLine>
<failsafe.argLine>-DdummyProperty=notUsed</failsafe.argLine>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
I recently ran into the same issue and even took implicitly the same steps as you described with the same result. No clean solution I found worked for me.
So I ran several steps in debug mode and it seems that Maven replaces properties twice. That is not just in a lazy manner, as I thought, but in both eager and lazy manner:
eagerly (before any goal is run) are replaced static properties (defined in properties section of POM and probably also settings.xml),
lazily (before each execution) are replaced dynamic properties.
This is where our step with setting a blank property as a default failed. Maven just went:
eager replace of default value (blank)
JaCoCo sets dynamic value
lazy replace of dynamic values (nothing to replace now, already used the blank value)
Finally the solution is to set the default value dynamically. This can be done with GMaven plugin like this:
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>set-default-values</id>
<phase>initialize</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
project.properties.'surefire.argLine' = ''
</source>
</configuration>
</execution>
</executions>
</plugin>
So now Maven goes:
eager replace of static properties
GMaven dynamically sets default value (if profile is active)
JaCoCo sets dynamic value
Surefire runs with correctly set argLine
With active profile the exec file is generated, with non-active profile the blank default value is used and build succeeds.
My solution to use argLine in the maven-surefire-plugin safely.
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<id>set-custom-arg-line</id>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
def argLine = project.properties['argLine'];
if (argLine == null) {
argLine = "";
}
project.properties.argLine = argLine;
</source>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<argLine>-Xmx1024m ${argLine}</argLine>
</configuration>
</plugin>
For me upgrading the version from 0.7.7.201606060606 to 0.7.9 also fixed this.
I had to explicitly add the version to the commandline (not just to the pom) because the build server kept using the old verison. This can be done as follows:
org.jacoco:jacoco-maven-plugin:0.7.9:prepare-agent
instead of
org.jacoco:jacoco-maven-plugin:prepare-agent
The jacoco plugin site (for sonar) states that argline must be added as a property. For me it also worken when using the #{argLine} in the surefire plugin settings.
Update the POM.xml as
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.1</version>
<configuration>
<argLine>${argLine} -XX:PermSize=256m -XX:MaxPermSize=1048m</argLine>
</configuration>
</plugin>
and then the most important thing is to run the Maven project with goals:
mvn jacoco:prepare-agent clean test jacoco:report
I have added a Maven/Java project with 1 domain class with the following features:
Unit or Integration testing with the plugins Surefire and Failsafe.
Findbugs.
Test coverage via Jacoco.
I kept the project as simple as possible. The project puts many suggestions from these and other posts together in an example project. Thank you, contributors!
The readme file gives a brief explanation. It explains how you can run either a user or an integration test with Jacoco.
Enjoy!

Setting properties in maven with gmaven

I am trying to overwrite the following property in maven using gmaven:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<executions>
<execution>
<id>setproperty</id>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
pom.properties['main.build.directory']=project.parent.build.directory.absolutePath.replace('\\','/');
</source>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
But I get this error:;
[ERROR] Failed to execute goal org.codehaus.gmaven:gmaven-plugin:1.5:execute (setproperty) on project my-project: startup failed, script139276
2592853.groovy: 1: expecting ''', found '<EOF>' # line 1, column 84.
[ERROR] 1 error
What is wrong with the above groovy snippet?
Value of a property which is set using gmavenplus-plugin displays correctly when accessed using the plugin. It will display correctly even if it is accessed using different instances of the same plugin.
Problem arises when value of a property which is already initialized outside the plugin is altered by the plugin and it is accessed outside the plugin. Now the value of the property is not the value as updated by plugin. The updated value is now scoped within the plugin. As a workaround to solve this issue if a property has to be updated by the plugin and is required to be accessed outside the scope of plugin: do not declare or initialize it, in case it needs to be then declare and initialize the property through the plugin.
I agree with #khmarbaise that this is a little weird to do, but if you must...I'm not sure offhand why it isn't working. That plugin isn't really maintained anymore. <shamelessPlug>I think this should work:
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>setproperty</id>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<scripts>
<script><![CDATA[project.properties['main.build.directory']=project.parent.build.directory.replace('\\','/')]]></script>
</scripts>
</configuration>
</execution>
</executions>
</plugin>
For more info on this mojo, check out http://groovy.github.io/GMavenPlus/execute-mojo.html.
</shamelessPlug>. However, be aware that I believe this will be scoped within the plugin.

Maven exec bash script and save output as property

I'm wondering if there exists a Maven plugin that runs a bash script and saves the results of it into a property.
My actual use case is to get the git source version. I found one plugin available online but it didn't look well tested, and it occurred to me that a plugin as simple as the one in the title of this post is all I need. Plugin would look something like:
<plugin>maven-run-script-plugin>
<phase>process-resources</phase> <!-- not sure where most intelligent -->
<configuration>
<script>"git rev-parse HEAD"</script> <!-- must run from build directory -->
<targetProperty>"properties.gitVersion"</targetProperty>
</configuration>
</plugin>
Of course necessary to make sure this happens before the property will be needed, and in my case I want to use this property to process a source file.
I think you could utilize gmaven plugin for this task:
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<properties>
<script>git rev-parse HEAD</script>
</properties>
<source>
def command = project.properties.script
def process = command.execute()
process.waitFor()
project.properties.gitVersion = process.in.text
</source>
</configuration>
</execution>
</executions>
</plugin>
After execution of this script you should be able to refer to ${gitVersion} property.

Configuring Javadoc aggregation in Maven

I'm trying to create an aggregate Javadoc site for all the modules in my project, but I can't seem to configure the plugin in a way that is satisfactory. Mainly, I can't seem to get it to aggregate the javadocs all the while detecting links and excluding certain packages. Essentially, it appears the configuration of the plugin is ignored entirely.
I have a root pom.xml that refers to a bunch of submodules and contains the following configuration:
<modules>
<module>foo</module>
<module>bar</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.maven.apache.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<executions>
<execution>
<id>aggregate</id>
<phase>site</phase>
<goals>
<goal>aggregate</goal>
</goals>
<configuration>
<links>
<link>http://docs.oracle.com/javase/6/docs/api</link>
<link>http://static.netty.io/3.5/api</link>
<link>http://google-guice.googlecode.com/git/javadoc</link>
<link>http://docs.guava-libraries.googlecode.com/git-history/release/javadoc</link>
<link>http://fasterxml.github.com/jackson-databind/javadoc/2.0.4</link>
<link>https://developers.google.com/protocol-buffers/docs/reference/java</link>
</links>
<bootclasspath>${sun.boot.class.path}</bootclasspath>
<additionalJOption>-J-Xmx1024m</additionalJOption>
<detectJavaApiLink>true</detectJavaApiLink>
<detectLinks>true</detectLinks>
<excludePackageNames>*.testing.*</excludePackageNames>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
But when I run mvn javadoc:aggregate with this setup, I end up with a javadoc site that has no links to any of the referenced libraries and still includes all the testing classes.
I don't even see the plugin attempting to download the package-list for each declared link source.
On the other hand, generating the javadoc for each individual module works well and as expected.
What am I getting wrong?
Plugin configurations can be placed on two levels; inside the execution tag or outside of it ("global").
When the configuration is inside the execution tag it belongs to that particular execution. In your case you will have to run mvn site for it to execute since it is bound to that phase.
When the mvn javadoc:aggregate command is used it looks for the "global" configuration. In your pom there is no such configuration and thus it uses the default configuration.
Change your plugin configuration to this instead:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<configuration>
<links>
<link>http://docs.oracle.com/javase/7/docs/api</link>
<link>http://static.netty.io/3.5/api</link>
<link>http://google-guice.googlecode.com/git/javadoc</link>
<link>http://docs.guava-libraries.googlecode.com/git-history/release/javadoc</link>
<link>http://fasterxml.github.com/jackson-databind/javadoc/2.0.4</link>
<link>https://developers.google.com/protocol-buffers/docs/reference/java</link>
</links>
<bootclasspath>${sun.boot.class.path}</bootclasspath>
<additionalJOption>-J-Xmx1024m</additionalJOption>
<detectJavaApiLink>true</detectJavaApiLink>
<detectLinks>true</detectLinks>
<excludePackageNames>*.testing.*</excludePackageNames>
</configuration>
<executions>
<execution>
<id>aggregate</id>
<phase>site</phase>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
You can place a configuration inside the execution part to override and specialize the configuration for that execution.
BTW The <groupId> is wrong in your pom. It should be
<groupId>org.apache.maven.plugins</groupId>
and not
<groupId>org.maven.apache.plugins</groupId>

Resources