JaCoCo Report Format - java

For my small Java/Maven application , I am using JaCoCo in my POM.xml as under:
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.6.201602180812</version>
<configuration>
<destFile>${basedir}/target/coverage-reports/jacoco.exec</destFile>
</configuration>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
As long as I dont use the <destFile> parameter, the default reports in target/site/jacoco folder are correctly generated in XML, CSV and HTML format. But when I use the <destFile> element in order to change the default folder where the reports are generated, only the jacoco.exec file is generated and nothing else. How can I change the report folder as well as get the reports in csv, xml and html formats?

With the destFile parameter, you changed the location where the prepare-agent goal will write the execution data file. By default, this is ${project.build.directory}/jacoco.exec, meaning (still by default) target/jacoco.exec. However, the report goal expects the path to the execution file to be passed in the dataFile parameter, which, of course, defaults to ${project.build.directory}/jacoco.exec, so that they are in sync. Therefore, if you want to change the path to this execution file, you need to match those two parameters. In order not to duplicate the path, you can use a Maven property to do that:
<properties>
<jacoco.execution.file>${project.build.directory}/coverage-reports/jacoco.exec</jacoco.execution.file>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version>
<configuration>
<destFile>${jacoco.execution.file}</destFile>
<dataFile>${jacoco.execution.file}</dataFile>
</configuration>
<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>
</plugins>
</build>
Note that this will not change the output directory of the JaCoCo reports; this just changes the path to the execute file. For that, you can use the outputDirectory parameter:
Output directory for the reports. Note that this parameter is only relevant if the goal is run from the command line or from the default build lifecycle. If the goal is run indirectly as part of a site generation, the output directory configured in the Maven Site Plugin is used instead.
and have the following configuration element added:
<configuration>
<!-- rest of your JaCoCo configuration -->
<outputDirectory>${project.build.directory}/coverage-reports/jacoco</outputDirectory>
</configuration>
This will make sure all of the HTML, XML, and CSV reports are generated under target/coverage-reports/jacoco. Take note that this configuration will not be used as part of the Maven Site generation when launching mvn site. During site generation, you'll need to configure the outputDirectory of the maven-site-plugin instead.

Related

why do I not find generated source files for grpc and protobuf when using maven and java in vscode

I have a pom file that correctly generates the grpc and protobuf source files I need in target/generated-sources when run from the command line. But when I build in vscode those directories are empty and references to the protobufs are undefined. Here's the section of my pom file that builds the grpc source.
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.2.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
I added the following based on what I read in other posts to prevent vscode/eclipse from removing the generated source directories
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>target/generated-sources/protobuf/grpc-java</source>
<source>/target/generated-sources/protobuf/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
When vs-code builds, the target generated-source directories are there, but there is no source in them. We had a similar problem with intellij but were able to work around it by running the maven command line build before opening intellij but that does not seem to work for vscode.
Use protoc-jar-maven-plugin instead.
Sample usage please view protoc-jar-maven-plugin.

Save exec output to <properties></properties> section of pom.xml for use in later maven phase

I have a maven java project that docker builds a docker image and then docker saves the image as an artifact of the build using the io.fabric8.docker-maven-plugin plugin.
When I build the docker image, I would like to get the size and add it to metadata so we can see how big the image is before it is uncompressed.
The io.fabric8.docker-maven-plugin plugin does not have a way of getting the exact size of generated docker image, so I am currently using the org.codehaus.mojo.exec-maven-plugin plugin to grab the size of the image like so:
<plugin>
<!-- generate metadata about docker image -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<id>generate-docker-metadata</id>
<phase>generate-resources</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>docker</executable>
<commandlineArgs>image inspect ${project.docker.image}:${project.version} --format='{{.Size}}' >> ${project.basedir}/src/main/resources/META-INF/Docker-Image-Size</commandlineArgs>
<workingDirectory>.</workingDirectory>
</configuration>
</execution>
</executions>
</plugin>
Currently I can put the output into the Docker-Image-Size file, but I need a way to make it available as a property that can be referenced in the meta-data section that generates the meta-data file.
How can I save this exec output to the <properties>/<properties> section of the pom.xml file to be used later in a different phase?
Do I need to use a properties file, or can I just save it as ${docker.image.size}?
I cannot directly edit any properties that already exist in the <properties>/<properties> section of the pom.xml.
However, the answer I came up with is to use the org.codehaus.gmaven.gmaven-plugin plugin to run shell script, edit the output, and save it to a variable that can be used later in the pom.xml file. Note that his variable is not actually defined anywhere in the file except for in the org.codehaus.gmaven.gmaven-plugin plugin section.
(Putting an empty variable in the <properties>/<properties> section of the pom.xmlalways makes the variable empty.)
I used the org.codehaus.gmaven.gmaven-plugin plugin like so:
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<properties>
<script>docker image inspect ${project.docker.image}:${project.version} --format='{{.Size}}</script>
</properties>
<source>
def command = project.properties.script
def process = command.execute()
process.waitFor()
def text = process.in.text.trim()
// Remove single quotes that surround number output
def number = text.substring(1, text.length()-1);
project.properties.dockerImageSize = number
</source>
</configuration>
</execution>
</executions>
</plugin>
The metadata section then uses the variable like so:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.4.0</version>
<extensions>true</extensions>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
<configuration>
<instructions>
<Bundle-Category>Thing</Bundle-Category>
<Bundle-Activator>com.company.thing.impl.Activator</Bundle-Activator>
<Bundle-Vendor>${company.vendor}</Bundle-Vendor>
<Bundle-ContactAddress>${company.contactAddress}</Bundle-ContactAddress>
<Bundle-Copyright>${company.copyright}</Bundle-Copyright>
<Bundle-LicenseType>${company.licenseType}</Bundle-LicenseType>
<Bundle-Description>${company.description}</Bundle-Description>
<Bundle-DockerImageSize>${dockerImageSize}</Bundle-DockerImageSize>
<Import-Package>
com.company.thing.api*;version="[0.0.10,1.0.0)",
*
</Import-Package>
</instructions>
</configuration>
</plugin>

How to review file names format with maven

I am trying to find a way to review the files generated by running mvn install, my task basically is, review if the total characters in the name are correct, if at least one file name is not complying, I should make certain task.
Is this possible in a pom with maven?
you can use dependency:analyze for that,
[https://maven.apache.org/plugins/maven-dependency-plugin/analyze-mojo.html]
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>analyze</id> <!-- notice the execution id "analyze" -->
<goals>
<goal>analyze</goal>
</goals>
<configuration>
<ignoreNonCompile>true</ignoreNonCompile>
</configuration>
</execution>
</executions>

Maven custom packaging

I am using a library (RootBeer), which requires an additional build step: after creating my JAR, I have to run the RootBeer JAR with my JAR as its parameter to create the final RootBeer-enabled JAR.
E.g., if my jar is myjar.jar, this is how I have to create the final artefact myjar-final.jar with RootBeer:
java -jar rootbeer.jar myjar.jar myjar-final.jar
I would like to know if there is a mechanism in Maven which would enable me to build an artifact in this way.
Right now I'm using the gmaven-plugin with a Groovy script, but this just feels too hacky, and I'm pretty sure I couldn't use the resulting artefact as a Maven dependency in other projects:
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<executions>
<execution>
<id>groovy-magic</id>
<phase>package</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
println """java -jar target/rootbeer-1.2.0.jar target/myjar.jar target/myjar-final.jar"""
.execute().in.eachLine {
line -> println line
}
</source>
</configuration>
</execution>
</executions>
</plugin>
Any suggestions?
You can use the exec-maven-plugin to execute the final step what you have implemented into Groovy furthermore you need to added build-helper-maven-plugin to add the supplemental artifact to Maven to get it deployed with the rest of your artifacts.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- The main class of rootbeer.jar -->
<mainClass>org.trifort.rootbeer.entry.Main</mainClass>
<!-- by setting equal source and target jar names, the main artefact is
replaced with the one built in the final step, which is exactly what I need. -->
<arguments>
<argument>${project.build.directory}/${project.artifactId}.jar</argument>
<argument>${project.build.directory}/${project.artifactId}.jar</argument>
<argument>-nodoubles</argument>
</arguments>
</configuration>
</plugin>

Generating sources by running a project's java class in Maven

I'm converting a largish Ant build to Maven. As part of the Ant build, we have several steps which created Java classes by invoking one of the project's classes, simplified as:
javac SomeGenerator.java
java SomeGenerator generated # generate classes in generated/
javac generated/*.java
I've split each generator in its own Maven module, but I have the problem of not being able to run the generator since it's not yet compiled in the generate-sources phase.
I've tried something similar to
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1.1</version>
<executions>
<execution>
<id>generate-model</id>
<goals>
<goal>java</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<mainClass>DTOGenerator</mainClass>
<arguments>
<argument>${model.generated.dir}</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
Which sadly does not work, for the reasons outlined above. Splitting the code generators into two projects each, one for compiling the generator and another for generating the DTOs seems overkill.
What alternatives are there?
Using Maven 2.2.1.
You can execute the maven-compile-plugin in the generate-sources phase. Just add another execution before the existing execution and configure it so that it just picks up the sources for the generator.
Or split the project in two: build the generator with a separate POM and include the generator library as a dependency to the POM that's generating the sources.
Personally I would split the project. Keeps the build files cleaner and easier to maintain.
I didn't want to have 2 different projects, so I tried to setup Maven for adding the generated compiled code to the final jar package.
This is the working solution I've used:
In process-classes phase (executed just after the compile phase):
exec-maven-plugin for executing a main class able to generate my source files in target/generated-sources/java folder (in my specific case I used the Roaster library for source code generation);
build-helper-maven-plugin for adding the generated sources in the correct location
In prepare-package phase:
maven-compiler-plugin, in order to detect the changes and recompile the module
maven-jar-plugin for producing the jar package
This is my pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.example.MyClassWriter</mainClass>
<arguments>
<argument>${project.basedir}</argument>
<argument>${project.build.directory}</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<phase>prepare-package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
In order to do this in one project, there are 3 steps:
Compile generator code
We can do it in generate-sources phase, using maven-compiler-plugin. You can also exclude other source files.
Run generator to generate code
We can do it in process-sources phase, using exec-maven-plugin.
Compile project
Below is the key part of pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
<executions>
<execution>
<id>compile-generator</id>
<phase>generate-sources</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<includes>
<include>source/file/of/generator/*.java</include>
</includes>
<excludes>
<exclude>other/source/files/*.java</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>generate-codes</id>
<goals>
<goal>java</goal>
</goals>
<phase>process-sources</phase>
<configuration>
<mainClass>your.main.class.of.generator</mainClass>
</configuration>
</execution>
</executions>
</plugin>
We faced the same problem. We wanted to respect Maven's behavior as closely as possible, to have no problems with plugins and so on... Fighting Maven is just too expensive!
We realized that the update frequency of the generated code was usually very different from the one of the code that we manually write, so separating the code had very good performance characteristics for the build. So we accepted to have our generated classes as a dependency of the manually written.
We adopted the following structure, that had just one little change from a regular maven config, a change in the source directory.
Parent project : Generations
We created a parent project for all our generations.
It has a JAR type if it contains code to be compiled, otherwise POM.
There we have our generating code, in /src.
It can compile in /target as usual.
It runs the generation, each generator producing code in a sub-directory of /target.
Note: if you want several generated results in the same jar, just put them in the same sub-directory.
Child jar projects : Generateds
It is a subdirectory of the Generations project.
It has a JAR type.
The source directory points to the sub-directory in the parent's target.
<sourceDirectory>../target/generated1</sourceDirectory>
It compiles normally in its own /target directory.
That structure allows us to :
have as little modification to the standard maven layout as possible, so every maven command and plugin keeps working nicely.
scale nicely if you have several generators,
scale nicely if you want to generate several jars (we had a case wsdl2java where one generator produced code that should be split into several jars ; each child generated project would have the same source directory, but would be configured with an <includes> to handle only some of the classes).
I posted a minimal working setup here https://github.com/baloise/inlinesourcecodegenerator
It uses build-helper compiler and exec plugins and has all code in the same project.

Categories