Starting with the sample from https://docs.gradle.org/current/samples/sample_jvm_multi_project_with_code_coverage.html (i.e., the code here https://github.com/gradle/gradle/tree/master/subprojects/docs/src/samples/java/jvm-multi-project-with-code-coverage ) and simply adding Spring Boot by changing application/build.gradle
to
plugins {
id 'myproject.java-conventions'
id 'application'
}
dependencies {
implementation project(':list')
implementation project(':utilities')
implementation 'org.springframework.boot:spring-boot-starter-web:2.3.8.RELEASE' // <-- this line is new
}
application {
mainClass = 'org.gradle.sample.Main'
}
and changing application/src/main/java/org/gradle/sample/app/Main.java
to
package org.gradle.sample.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.gradle.sample.list.LinkedList;
import static org.gradle.sample.utilities.StringUtils.join;
import static org.gradle.sample.utilities.StringUtils.split;
import static org.gradle.sample.app.MessageUtils.getMessage;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
LinkedList tokens;
tokens = split(getMessage());
System.out.println(join(tokens));
SpringApplication.run(Main.class, args);
}
}
will break the example (full working, or rather non-working example here: https://github.com/SamuelBucheliZ/gradle-jvm-multi-project-with-code-coverage/tree/57e57b8bf24ef4208d9a03a361714c916701e599 ).
When calling
./gradlew clean build codeCoverage -stacktrace
it will fail with
> Task :code-coverage-report:codeCoverageReport FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':code-coverage-report:codeCoverageReport'.
> Error while creating report
* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':code-coverage-report:codeCoverageReport'.
[...]
Caused by: java.io.IOException: Error while analyzing log4j-api-2.13.3.jar@org/apache/logging/log4j/util/ProcessIdUtil.class.
at org.jacoco.core.analysis.Analyzer.analyzerError(Analyzer.java:162)
at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:134)
at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:157)
at org.jacoco.core.analysis.Analyzer.analyzeAll(Analyzer.java:193)
at org.jacoco.core.analysis.Analyzer.analyzeZip(Analyzer.java:265)
at org.jacoco.core.analysis.Analyzer.analyzeAll(Analyzer.java:196)
at org.jacoco.ant.ReportTask.createBundle(ReportTask.java:573)
at org.jacoco.ant.ReportTask.createReport(ReportTask.java:545)
at org.jacoco.ant.ReportTask.execute(ReportTask.java:496)
... 251 more
Caused by: java.lang.IllegalStateException: Can't add different class with same name: org/apache/logging/log4j/util/ProcessIdUtil
at org.jacoco.core.analysis.CoverageBuilder.visitCoverage(CoverageBuilder.java:106)
at org.jacoco.core.analysis.Analyzer$1.visitEnd(Analyzer.java:99)
at org.objectweb.asm.ClassVisitor.visitEnd(ClassVisitor.java:378)
at org.jacoco.core.internal.flow.ClassProbesAdapter.visitEnd(ClassProbesAdapter.java:100)
at org.objectweb.asm.ClassReader.accept(ClassReader.java:722)
at org.objectweb.asm.ClassReader.accept(ClassReader.java:401)
at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:116)
at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:132)
... 258 more
* Get more help at https://help.gradle.org
BUILD FAILED in 8s
19 actionable tasks: 19 executed
I have a suspicion that this may be related to https://github.com/jacoco/jacoco/issues/407 . However, my question is whether there is any way to fix this problem. Unfortunately, the official documentation at https://docs.gradle.org/current/userguide/jacoco_plugin.html does not provide any guidance on this topic.
As far as I can tell, the problematic line is https://github.com/SamuelBucheliZ/gradle-jvm-multi-project-with-code-coverage/blob/57e57b8bf24ef4208d9a03a361714c916701e599/buildSrc/src/main/groovy/myproject.jacoco-aggregation.gradle#L38
// Task to gather code coverage from multiple subprojects
def codeCoverageReport = tasks.register('codeCoverageReport', JacocoReport) {
additionalClassDirs(configurations.runtimeClasspath) // <-- this line here
additionalSourceDirs(sourcesPath.incoming.artifactView { lenient(true) }.files)
executionData(coverageDataPath.incoming.artifactView { lenient(true) }.files.filter { it.exists() })
reports {
// xml is usually used to integrate code coverage with
// other tools like SonarQube, Coveralls or Codecov
xml.enabled true
// HTML reports can be used to see code coverage
// without any external tools
html.enabled true
}
}
Removing it will make the build work again. However, then the code coverage report is empty. Is there any way to adjust it, so it will only include code from the project itself, but not external jars, etc.?
Just do that and you will be fine (all external classes will be excluded):
additionalClassDirs(configurations.runtimeClasspath.get().filter{it.path.contains(rootProject.name) })
This works with a Kotlin DSL , with Groovy you might have to change the code a little bit maybe this way :
additionalClassDirs(configurations.runtimeClasspath.filter{it.path.contains(rootProject.name) })