I am new to maven and our project has several modules. my goal is generate one coverage report for the entire project (that has all the modules). below is the rough skeleton of our Based on project's POM.xml
<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>1.0.0</modelVersion>
<groupId>com.xx.test</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>test</name>
<modules>
<module>module1</module>
<module>module2</module>
<module>module3</module>
<module>module4</module>
<module>module5</module>
</modules>
<build>
.
.
.
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>emma-maven-plugin</artifactId>
<version>1.0-alpha-3</version>
</plugin>
</plugins>
</reporting>
</project>
as you see above i have added emma plug-in and executed following : mvn emma:emma
This is generating individual coverage reports for each module under the dir called 'target'. is there a way i can consolidate all these reports into one report?
any pointers..?
Following is the approach to achieve required results
add a JaCoCo plugin to the parent pom.xml so all projects could generate a coverage report.
create new module ‘coverage’ for appending all the results of the Jacoco plugin…this is just one time thing.
in pom.xml of this new module, insert the required plugins to join all the coverage information
a. define all properties where all the classes,sources,generated-sources etc, since the JaCoCo report plugin requires you set the location of the build directory, class directory, source directory or generated-source directory
b. we are using ANT task with Maven. JaCoCo Ant task will merge results from multiple JaCoCo file results
now from parent pom.xml run : mvn clean install
if module has any test cases , ‘jacoco.exec’ file will be generated for that module (this file has all the coverage information that is required for reporting), individual module code coverage reporting is also generated at this point (under \target\site\jacoco)
and finally from ‘coverage’ pom.xml run : mvn clean install
a. this is going to run ANT reporting task within maven that will grab all the generated ‘jacoco.exec’ files for all the modules, merge the results and generate the report.
Below is the ANT reporting target that can be run within maven
<?xml version="1.0" encoding="UTF-8" ?>
<project name="maven-antrun-" default="main" >
<target name="main">
<echo message="Generating JaCoCo Reports"/>
<taskdef name="report" classname="org.jacoco.ant.ReportTask">
<classpath path="./target/jacoco-jars/org.jacoco.ant.jar"/>
</taskdef>
<mkdir dir="./target/coverage-report"/>
<report>
<executiondata>
<fileset dir="../module1/target">
<include name="jacoco.exec"/>
</fileset>
<fileset dir="../module2/target">
<include name="jacoco.exec"/>
</fileset>
</executiondata>
<structure name="Project Code Coverage">
<group name="project">
<classfiles>
<fileset dir="../module1/target/classes"/>
<fileset dir="../module2/target/classes"/>
</classfiles>
<sourcefiles encoding="UTF-8">
<fileset dir="../module1/src/main/java"/>
<fileset dir="../module2/src/main/java"/>
</sourcefiles>
</group>
</structure>
<html destdir="./target/coverage-report/html"/>
<xml destfile="./target/coverage-report/coverage-report.xml"/>
<csv destfile="./target/coverage-report/coverage-report.csv"/>
</report>
</target>
</project>
Is there any way to do this generically for multiple submodules in the ant report task? Specifying the exact directories works OK, but not ** dirset references. This works OK:
<classfiles>
<dirset dir="${basedir}">
<include name="module1/target/classes"/>
<include name="module2/target/classes"/>
OR
<dirset dir="">
<include name="module1/target/classes"/>
<include name="module2/target/classes"/>
OR
<dirset dir="" includes="module1/target/classes,module2/target/classes"/>
These do not work (0 classes, or 'Error while creating report' with no further details):
<dirset dir="">
<include name="**/target/classes"/>
OR
<dirset dir="${basedir}">
<include name="**/target/classes"/>
OR
<dirset dir="" includes="**/target/classes"/>
OR
<dirset dir="${basedir}" includes="**/target/classes"/>
Interestingly, sourcefile ** references produces the HTML source links OK, I thought it worked exactly the same as classfiles:
<sourcefiles>
<dirset dir="" includes="**/src/main/java"/>
This does not work:
<sourcefiles>
<dirset dir="${basedir}" includes="**/src/main/java"/>
Related
I try to build a Maven project with classes generated from jaxb2-maven-plugin.
Consider the following minimal pom.xml:
<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>test</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<goals>
<goal>xjc</goal>
</goals>
<configuration>
<packageName>test</packageName>
<sources>
<source>src/main/resources/schema.xsd</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
And this minimal schema in src/main/resources/schema.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified" vc:maxVersion="1.1" vc:minVersion="1.0" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root" type="xs:string"/>
</xs:schema>
When invoking mvn clean compile, the project is built as expected. But when I specify the file using a path containing .., the following error occurs. When using a (relative or absolute) path without .., everything is fine.
C:\dev\test>mvn -f ..\test\pom.xml clean compile
[...]
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project test: Compilation failure: Compilation failure:
[ERROR] /C:/dev/test/target/generated-sources/jaxb/test/ObjectFactory.java:[32,8] duplicate class: test.ObjectFactory
How can I get rid of this error and build my project using mvn -f <some path containing "..">?
For me (on macOS), the issue goes away when I don't have a "." component in my path:
maven compile -f ./blah/blah # <-- "duplicate class" errors
maven compile -f blah/blah # <-- works fine
Ugly workaround: Try using an absolute path?
(Seems like a path normalization bug in Maven or maven-compiler-plugin.)
I've configured my project with SonarQube and Jacoco for code coverage. Everything works well except one thing. I divided project in many maven sub modules:
project (pom.xml) -
|-moduleA (no pom here)
| |- it (pom.xml) - integration tests for "impl" module
| |- impl (pom.xml) - implementaion + Unit tests
|-moduelB
| |- it (pom.xml) - integration tests for "impl" module
| |- impl (pom.xml) - implementaion + Unit tests
|-moduleC ...
I start build using following command:
mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent -Dmaven.compiler.debug=true install sonar:sonar
The problem is that Jacoco can easily support Unit test coverage inside the same module (so in my case Unit Tests inside impl module) but cannot analyze coverage from it module which itself does not contain any implementation classes. It just contains integration tests for impl module. It's clear for me why it doesn't work. I'm getting such info in Jacoco logs:
No JaCoCo analysis of project coverage can be done since there is no class files.
After I've defined sonar.java.binaries property inside moduleA/it/pom.xml like this:
<properties>
<sonar.java.binaries>../impl/target/classes</sonar.java.binaries>
</properties>
coverage analysis of it still fails, but message in Jacoco logs changes to:
[INFO] Analysing D:\project\moduleA\it\target\jacoco.exec
[WARNING] Coverage information was not collected. Perhaps you forget to include debug information into compiled classes?
I must mention that D:\project\moduleA\it\target\jacoco.exec file exists. I also checked that compiled classes in D:\project\moduleA\impl\target\classes contain debug data (all lines, vars and source).
I was trying with different paths inside sonar.java.binaries but result is always the same. I've tried:
../impl/target/classes
../../impl/target/classes
../../../impl/target/classes
../impl/target
...
How can I configure Jacoco (Sonar) to allow it to find classes binaries in different maven sub module related to jacoco.exec file?
Based on this question, I resorted to the Maven Ant plugin with JaCoCo's ant task library, which allows richer inclusion trees:
<project ...>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<dependencies>
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.ant</artifactId>
<version>${jacoco.version}</version>
</dependency>
<dependency>
<groupId>ant-contrib</groupId>
<artifactId>ant-contrib</artifactId>
<version>20020829</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>report-it-coverage</id>
<phase>post-integration-test</phase>
<goals><goal>run</goal></goals>
<configuration>
<skip>${skipITs}</skip>
<target name="report-it-coverage">
<taskdef name="jacoco-report" classname="org.jacoco.ant.ReportTask" classpathref="maven.plugin.classpath" />
<taskdef resource="net/sf/antcontrib/antcontrib.properties" classpathref="maven.runtime.classpath" />
<available file="${jacoco.it-coverage.data}" property="jacoco.exec.file.exists" />
<if>
<equals arg1="${jacoco.exec.file.exists}" arg2="true" />
<then>
<echo>Analyzing ITs coverage data from '${jacoco.it-coverage.data}'</echo>
<jacoco-report>
<executiondata>
<file file="${jacoco.it-coverage.data}" />
</executiondata>
<structure name="ROOT">
<classfiles>
<fileset dir="${project.basedir}/${project.parent.relativePath}">
<include name="**/target/classes/my/company/package/**/*.class" />
<exclude name="**/target/classes/my/test/glue/**/*" />
</fileset>
</classfiles>
</structure>
<html destdir="${project.reporting.outputDirectory}/jacoco-it" />
<xml destfile="${project.build.directory}/jacoco.xml" />
</jacoco-report>
</then>
<else>
<echo>Missing ITs coverage data file '${jacoco.it-coverage.data}'</echo>
</else>
</if>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
I have a Maven ant plugin that bundles up a library of Ant tasks. One of them has a lot of CI tasks.
I have the plugin working and can hit the task by running
mvn -U ci:options
This brings up a menu for the different operations.
The issue i'm having is that I need to resolve dependencies in the pom before the task is executed.
From reading up I would have thought that I could add
<execution>
<goal>dependency:unpack-dependencies</goal>
</execution>
To the pluginMetaData xml file that defines the mojo, though this doesn't seem to do anything
ci.mojos.xml
<pluginMetadata 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/plugin-metadata-1.0.0.xsd">
<mojos>
<mojo>
<!-- target name to call in ant script -->
<call>run</call>
<!-- mojo goal name -->
<goal>options</goal>
<execution>
<goal>dependency:unpack-dependencies</goal>
</execution>
<parameters>
<parameter>
<name>artifactId</name>
<property>artifactId</property>
<required>true</required>
<readonly>true</readonly>
<type>java.lang.String</type>
<defaultValue>${project.artifactId}</defaultValue>
<description>Project Artifact Id</description>
</parameter>
....
ci.build.xml
<property name="project.home" location="."/>
<property name="target.dir" value="${project.home}/target"/>
<property name="build.dir" value="${target.dir}/build"/>
<property name="dependency.dir" value="${target.dir}/dependency"/>
<!-- Add contrib to the classpath -->
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<!-- Include ant utils from the shared resource -->
<include file="${dependency.dir}/shared_ant/build.xml"/>
<!-- Continuous Integration Options -->
<target name="run" description="Continuous Integration Options">
<ci.options/>
</target>
</project>
Any help greatly appreciated.
James
Currently running into a weird problem with a Maven build that is making a call to ant, within the parent pom the following property is defined: -
<jboss.home>${env.JBOSS_HOME}</jboss.home>
I am trying to override this by passing in -Djboss.home when I run Maven.
This build contains a profile that when activate calls an Ant build: -
<ant antfile="build.xml" inheritRefs="true">
<target name="all"/>
</ant>
The Ant script uses the property: -
<property name="jboss.dir" value="${jboss.home}"/>
An subsequently outputs it: -
<echo message="jboss dir is: ${jboss.dir}"/>
The problem is that the value it output is ${env.JBOSS_HOME}
Other properties in the parent pom I can override from the command line.
Even the jboss.home property does appear to be overridden if use elsewhere within the Maven build.
After trying various combinations of command it almost appears that the set of properties passed to Ant are resolved from the poms BEFORE any overrides from the command line. If I set the JBOSS_HOME environment variable then all places this variable is used have the correct values.
Is there something I am missing to be able to override this variable on the command line and have the overridden value used in the Ant script?
Stumbled into this problem today, and did discover an answer. This link provides some background: http://technotes.khitrenovich.com/properties-resolution-maven-implications-antrun-plugin/
Maven properties will work just fine if the property is referenced inline within the <target>. e.g:
<execution>
..
<configuration>
<target>
<echo message="Command-line override of external.property will work OK like this: ${external.property}"/>
</target>
</configuration>
</execution>
However, if you use an external ant file written like this, many/most properties will work, BUT command-line overrides will not be passed into the ant file. You will get the non-overridden value instead.
<execution>
..
<configuration>
<target>
<property name="external.property" value="${external.property}" />
<ant antfile="build.xml" target="all" />
</target>
</configuration>
</execution>
Instead, for external ant files, use this syntax. The command line value will be passed through correctly to the external antfile:
<execution>
..
<configuration>
<target>
<ant antfile="build.xml" target="all" >
<property name="external.property" value="${external.property}" />
<ant/>
</target>
</configuration>
</execution>
The problem is that ${env.JBOSS_HOME} is a system environment variable and you are instead passing to the JVM a system property -Djboss.home=.... These are two different things. Apart from that, any variables, args and so on in the Java world are case sensitive.
You seem do be doing all the right things, it works for me, I have made a working example with 2 pom.xml files. The parent pom looks like this:
<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>com.stackoverflow.test</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<name>Test</name>
<packaging>pom</packaging>
<modules>
<module>test-ant-properties</module>
</modules>
<properties>
<jboss.home>${env.JBOSS_HOME}</jboss.home>
</properties>
</project>
Then I created a module pom.xml in the sub-folder test-ant-properties that looks like this:
<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>
<parent>
<groupId>com.stackoverflow.test</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
</parent>
<artifactId>test-ant-properties</artifactId>
<name>Test maven ant properties</name>
<profiles>
<profile>
<id>jboss</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>jboss-ant</id>
<phase>install</phase>
<configuration>
<target>
<property name="jboss.dir" value="${jboss.home}"/>
<echo message="jboss dir is: ${jboss.dir}"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
I don't have JBOSS installed so for testing purpose I set the environement variable to test1234 like this:
set JBOSS_HOME=test1234
When I execute the parent pom with the jboss profile
mvn install -Pjboss
I get the following result: [echo] jboss dir is: test1234
When I execute the same command with the jboss.home setting
mvn install -Pjboss -Djboss.home=my_custom_variable
I get the following result: [echo] jboss dir is: my_custom_variable
there is -f option in maven, that allows to specify alternate pom.xml file. Is there a possibility, that I can also bring this behaviour to the executed modules? Now it looks like, that when I have this structure: projectA: pom.xml pom.xml2
projectB: pom.xml pom.xml2
And when I run maven with -f pom.xml2 option as reactor with projectB specified as module, it looks like that it picks pom.xml2 from the projectA, and it picks pom.xml from projectB. Is there a way, how can I propagate the -f option to the modules?
Thanks for answering.
Because we can specified pom file in module definition.1
Here's an example for using alternative pom file in module.
<modules>
<module>child1/pom-jdk14.xml</module>
<module>child2/pom-jdk14.xml</module>
</modules>
As Jörn Horstmann comments I would try lots of things to get this working with profiles in one pom.
If that's not possible the only way I can think of to get this working is to bypass the normal maven mechanism by using a "switching pom" with profiles. This pom is put as pom.xml in each module and has a profile for each of your pom.xml2 (or others) and in that profile executes another maven build f.e. via the antrun-plugin with the -f for the pom you need:
<profile>
<id>xml2</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>build pom.xml2</id>
<phase>prepare-package</phase> <!-- whatever suits you -->
<configuration>
<target>
<echo level="info" message="Building pom.xml2..." />
<exec executable="cmd" dir=".">
<arg value="/c" />
<arg value="mvn" />
<arg value="-f" />
<arg value="pom.xml2" />
<arg value="install" /> <!-- enter which phase you need -->
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>