Expected Behavior
jacocoTestReport work
Current Behavior
jacocoTestReport SKIPPED
Context
I created a task whose type is Test, and jacocoTestReport depends on the task. When I ran the task, jacocoTestReport did not work and I got the following information
jacocoTestReport SKIPPED
I find if I use the task test directly, jacocoTestReport worked fine. It makes me confused
the following code caused the above issue
buildscript {
repositories {
mavenCentral()
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath files ('Build\\Jars\\gradle-jboss-modules-1.0.jar')
//classpath "com.moowork.gradle:gradle-node-plugin:1.2.0"
classpath 'com.github.node-gradle:gradle-node-plugin:2.2.3'
classpath "gradle.plugin.com.srcclr:gradle:3.1.7"
}
}
plugins {
id 'com.jfrog.artifactory' version '4.11.0'
id 'org.sonarqube' version '2.7'
id "jacoco"
id "java"
}
if (project.hasProperty('srcclrtoken')) {
apply plugin: "com.srcclr.gradle"
srcclr {
apiToken = project.getProperty('srcclrtoken')
}
}
org.apache.tools.ant.DirectoryScanner.removeDefaultExclude("**/CVS")
org.apache.tools.ant.DirectoryScanner.removeDefaultExclude("**/CVS/**")
import static com.github.zhurlik.Ver.V_1_1
import org.apache.tools.ant.filters.ReplaceTokens
import org.apache.tools.ant.filters.*
import org.gradle.plugins.ide.eclipse.model.Facet.FacetType
import org.gradle.plugins.ide.eclipse.model.WbResource
import org.gradle.plugins.ide.eclipse.model.WbDependentModule
apply from: 'dependencies.gradle'
apply plugin: 'com.github.zhurlik.jbossmodules'
apply plugin: 'maven-publish'
buildDir = 'gradlebuild'
//identify the version of gradle to use for the wrapper
wrapper {
gradleVersion = '6.3'
}
//artifactoryPublish.skip = true
//initialize the dynamic global build props. "Static" props come from gradle.properties
ext {
doDeploy = project.hasProperty('do.deploy') ? project.getProperty('do.deploy').toBoolean() : false
appEnv = project.hasProperty('app.env') ? project.getProperty('app.env').toLowerCase() : dev
versionDate = getDate()
versionLabel = project.hasProperty('versionLabel') ? project.getProperty('versionLabel') : ''
buildNumber = project.hasProperty('buildNumber') ? project.getProperty('buildNumber') : 1
webProjects = webProjectNames.split(',')
: ''
def slashPosition = versionLabel.lastIndexOf('/')
if (slashPosition > -1)
currentVersion = versionLabel[slashPosition+1..versionLabel.size()-1]
else
currentVersion = 'test'
set('buildInfo.build.name', 'Trax ' + versionLabel.replace('/', '_') )
set('buildInfo.build.number', buildNumber)
}
def getDate() {
def date = new Date()
def formattedDate = date.format('MM/dd/yyyy - hh:mma (z)')
return formattedDate
}
//initialize the repositories used by each projects build to retrieve required dependencies
allprojects {
group = 'com.reged.trax'
version = currentVersion + '-' + buildNumber
status = 'Integration'
repositories {
maven {
url 'http://artifacts.reged.com/artifactory/trax-dev-gradle-local'
content {
includeGroup "tapestry"
}
}
mavenCentral() {
content {
excludeGroupByRegex "javax\\.jms.*"
excludeGroupByRegex "javax\\.sql.*"
}
}
maven {
url "https://repository.apache.org/content/repositories/snapshots/"
}
maven {
url "https://maven.repository.redhat.com/ga/"
}
flatDir{
dirs "Common/jars"
}
maven {
url "https://redisson.pro/repo/"
}
mavenCentral()
}
if (it.name.startsWith("TraxLegacy")){
configurations.all {
resolutionStrategy {
//force "commons-io:commons-io:2.4", "javax.activation:activation:1.1.1", "org.hibernate:hibernate-validator:4.0.0.GA"/*,"javax.validation:validation-api:1.0.0.GA"*/
//force "commons-io:commons-io:2.4", "javax.activation:activation:1.1.1", "org.hibernate:hibernate-validator:5.4.3.Final"/*,"javax.validation:validation-api:1.0.0.GA-redhat-3"*/
//failOnVersionConflict()
force "antlr:antlr:2.7.7",
"com.fasterxml.jackson.core:jackson-annotations:2.10.5",
"com.fasterxml.jackson.core:jackson-databind:2.10.5",
}
//force versions for all 3rd party library sub-dependencies
resolutionStrategy.eachDependency {
//TRAX-52850: fix 3rd party library security vulnerabilities
if (it.requested.group ==~ /com\.fasterxml\.jackson.*/) {
it.useVersion '2.10.5'
}
//TRAX-52853: fix 3rd party library security vulnerabilities
if (it.requested.group ==~ /org\.apache\.xmlgraphics.*/ && it.requested.name ==~ /batik.*/) {
it.useVersion '1.9.1'
}
}
exclude group: 'bcel'
exclude group: 'jboss', module: 'javassist'
exclude group: 'javassist', module: 'javassist'
exclude group: 'xpp3', module: 'xpp3'
exclude group: 'commons-beanutils', module: 'commons-beanutils-core'
exclude group: 'org.apache.geronimo.specs', module: 'geronimo-jms_1.1_spec'
exclude group: 'org.slf4j', module: 'slf4j-jdk14'
exclude group: 'jdom'
exclude module: 'xmlParserAPIs'
exclude group: 'org.jboss.spec.javax.transaction', module: 'jboss-transaction-api_1.1_spec'
exclude group: 'com.sun.xml.bind'
exclude group: 'c3p0'
}
} else {
configurations.all {
resolutionStrategy {
//force "commons-io:commons-io:2.4", "javax.activation:activation:1.1.1", "org.hibernate:hibernate-validator:4.0.0.GA"/*,"javax.validation:validation-api:1.0.0.GA"*/
//force "commons-io:commons-io:2.4", "javax.activation:activation:1.1.1", "org.hibernate:hibernate-validator:5.4.3.Final"/*,"javax.validation:validation-api:1.0.0.GA-redhat-3"*/
"org.javassist:javassist:3.18.2-GA",
"org.jboss.logging:jboss-logging:3.2.1.Final",
"org.slf4j:slf4j-api:1.7.26",
"org.springframework:spring-orm:$springframeworkVersion",
"org.springframework:spring-web:$springframeworkVersion",
"org.javassist:javassist:$javassistVersion"
}
//force versions for all 3rd party library sub-dependencies
resolutionStrategy.eachDependency {
//TRAX-52850: fix 3rd party library security vulnerabilities
if (it.requested.group ==~ /com\.fasterxml\.jackson.*/) {
it.useVersion '2.10.5'
}
//TRAX-52853: fix 3rd party library security vulnerabilities
if (it.requested.group ==~ /org\.apache\.xmlgraphics.*/ && it.requested.name ==~ /batik.*/) {
it.useVersion '1.9.1'
}
}
}
}
}
configure(subprojects.findAll {!(it.getPath().startsWith(":wpServices"))}) {currProj ->
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'eclipse-wtp'
apply plugin: 'com.jfrog.artifactory'
apply plugin: 'maven-publish'
if (!currProj.name.startsWith("TraxLegacy")){
sourceCompatibility = 1.11
targetCompatibility = 1.11
}
eclipse {
classpath {
downloadSources = true
downloadJavadoc = true
defaultOutputDir = file('target/classes')
file.whenMerged {
entries.each {
if (it in org.gradle.plugins.ide.eclipse.model.AbstractClasspathEntry && it.kind == 'src' && it.toString().contains('output')) {
if (it.entryAttributes['gradle_used_by_scope'] == 'test') {
it.entryAttributes['test'] = true
it.output = 'target/test-classes'
} else {
it.output = 'target/classes'
}
}
}
}
}
jdt {
if (!currProj.name.startsWith("TraxLegacy")){
sourceCompatibility = 1.11
targetCompatibility = 1.11
javaRuntimeName = "JavaSE-11"
}
}
wtp {
component {
sourceDirs -= file('src/test/java')
sourceDirs -= file('src/test/resources')
}
/*facet {
facet name: 'jst.java', version: '1.8'
file {
//removing default jst.java facet version which eclipse's gradle tooling (buildship plugin) insists on adding
whenMerged { w ->
facets.removeAll { it.name == 'jst.java' && it.version != "1.8" && it.type == FacetType.installed}
}
}
}*/
}
}
if (currProj.name != 'Common') {
task sourcesJar(type: Jar) {
exclude '*.zip'
}
java {
withSourcesJar()
}
}
sourceSets {
main {
java {
srcDirs=['src/main/java']
excludes=['**/rebel.xml', '.gitkeep']
}
resources {
srcDirs=['src/main/java','src/main/resources']
excludes=['**/rebel.xml']
}
}
}
test {
ignoreFailures = rootProject.ignoreFailureProp.toBoolean()
reports.html.enabled = true
reports.junitXml.enabled = false
systemProperties = System.getProperties()
}
dependencies {
if (project.hasProperty("${currProj.name}Dependencies")) {
rootProject."${currProj.name}Dependencies".each {
add(it.configuration, it.dependency, it.options)
}
}
}
rootProject.tasks["sonarqube"].dependsOn tasks.build
}
//set up war & deploy tasks for the web projects
configure(subprojects.findAll {it.name in webProjects}) { currentProject ->
//println "configuring ${currentProject.name}"
apply plugin: 'war'
apply plugin: 'distribution'
if (currentProject.name != 'TraxLegacyWeb') {
eclipse {
wtp {
component {
minusConfigurations << configurations.compile
}
}
}
}
configurations {antconf}
if (doDeploy) {
dependencies {
antconf('ant-contrib:ant-contrib:1.0b3'){transitive=false}
}
ClassLoader antClassLoader = org.apache.tools.ant.Project.class.classLoader
configurations.antconf.each { File f ->
antClassLoader.addURL(f.toURI().toURL())
}
}
tasks.withType(War) {
if (appEnv != dev) {
rootSpec.filesMatching(['version.properties','WEB-INF/app.properties']) {
filter ReplaceTokens, tokens: [
"version.num": buildNumber.toString(),
"version.date": versionDate,
"version.label": versionLabel
]
}
}
rootSpec.exclude("**/.gitkeep")
rootSpec.exclude("**/rebel.xml")
}
def appName = rootProject.property("${currentProject.getName()}.app.name").toString()
def jbossServerName = rootProject.property("${currentProject.getName()}.jboss.server.name")
war {
if (currentProject.name != 'TraxLegacyWeb') {
rootSpec.filesMatching('*.jar') { details ->
if (!(details.file.path =~ "AuditTraxClient.jar")) {
if (!(details.file.path =~ "jazzy-core.jar")){
details.exclude()
}
}
}
}
//archiveName rootProject.property("${currentProject.getName()}.app.name")+'.war'
archiveBaseName = rootProject.property("${currentProject.getName()}.app.name")
exclude('**/node_modules')
}
jar {
baseName rootProject.property("${currentProject.getName()}.app.name")
}
distZip {
archiveName "$appName[$version+$jbossServerName].zip"
}
distributions {
main {
baseName = appName
contents {
into '/'
from war
from (project(':Build').file('jonCLI')) {
include 'generic-jon-bundle-descriptor.xml'
filter(ReplaceTokens, tokens: [
'APP.ISNAMED':appName,
'ARCHIVE.TYPE':"war",
'APP.VERSION':project.version.toString(),
'Generic JON Bundle Descriptor':"JON Bundle Descriptor for ${appName}".toString()])
rename('generic-jon-bundle-descriptor.xml', 'deploy.xml')
}
}
}
}
clean {
delete "deploy"
delete "${project.projectDir}/src/main/webapp/qrunner/node_modules"
}
publishing {
publications {
mavenJava(MavenPublication) {
from components.web
artifactId rootProject.property("${currentProject.getName()}.app.name")}}}}
configure(subprojects.findAll {!(it.name in ['Common','Build', 'RegedCommon', 'wpServices', 'wpConsoleLite', 'wpServicesCore', 'TraxLegacyWeb'])}) {
dependencies {
compileOnly project(path: ":RegedCommon", configuration: 'compileOnly')
testCompile project(path: ":RegedCommon", configuration: "testCompile")
testCompile project(':RegedCommon').sourceSets.test.output
}
}
jibxProjects.split(',').each { name ->
project(":$name") {
dependencies {
compileOnly (project(":Build")) { transitive = false }
["Bind", "Run", "Schema"].each {
compile libs."jibx${it}".dependency
}
compile libs.bcel.dependency
}
task doJibx(dependsOn: project(":Build").tasks.build) {
doLast {
ant.lifecycleLogLevel = "VERBOSE"
ant.taskdef(name: 'bind', classname: 'com.reged.ant.JibxCompile', classpath: configurations.compileClasspath.asPath)
//println configurations.compile.asPath + ";${sourceSets.main.output.classesDirs}"
ant.bind(verbose: 'false', classpath: configurations.compile.asPath + ";${sourceSets.main.java.outputDir}") {
fileset (dir: 'src/main/java/com/reged/model/xml/jibx/binding')
}
}
}
jar.dependsOn doJibx
}
}
//update the footer files
project(":RegedCommonUITap3") {
dependencies {
compile project(path: ":RegedCommon")
}
jar {
eachFile { copyDetails ->
if (copyDetails.path == 'com/reged/common/ui/components/Footer.html') {
filter(ReplaceTokens, tokens: [buildDate:versionDate,buildNum:buildNumber.toString(),buildLabel:versionLabel/*,"#feedbackLink#":"feedbackLink"*/])
}
}
}
}
project(":RegedCommonUITap5") {
dependencies {
compile project(path: ":RegedCommon")
compile project(":tapestry5-jquery-upload")
}
jar {
eachFile { copyDetails ->
if (copyDetails.path == 'com/reged/components/Footer.tml') {
filter(ReplaceTokens, tokens: [buildDate:versionDate,buildNum:buildNumber.toString(),buildLabel:versionLabel/*,"#feedbackLink#":"feedbackLink"*/])
}
}
}
}
tapestry3Projects.split(',').each { name ->
project(":$name") {
dependencies {
compile project(":RegedCommonUITap3")
}
}
}
tapestry5Projects.split(',').each { name ->
project(":$name") {
dependencies {
compile project(":RegedCommonUITap5")
project(":tapestry5-jquery-upload")
}
}
}
project(":HighchartsServerSideJar") {
dependencies {
compile project(path: ":RegedCommon")
}
}
angularProjects.split(',').each { name ->
project(":$name") {
//apply plugin: 'com.moowork.node'
apply plugin: "com.github.node-gradle.node"
clean {
//delete rootProject.file('.gradle/nodejs')
}
node {
version = '8.12.0'
download = true
distBaseUrl = 'http://artifacts.reged.com/artifactory/nodejs-dist-local/dist'
workDir = rootProject.file('.gradle/nodejs')
}
task angularBuild (type: NpmTask) {
args = ['run', 'build']
}
angularBuild.dependsOn(npm_install)
war.dependsOn(angularBuild)
}
}
def moduleProjects = subprojects.findAll {!(it.name in webProjects) && !(it.name in ['Common','Build','wpServices','wpConsoleLite','wpServicesCore'])}.collect{it.name}
configurations {
jdbc
buildProject
}
def projArts = []
dependencies {
jdbc project(path: ":Common", configuration: "jdbc")
['wsdl', 'ws-policy'].each{
jbossmodules ("org.apache.cxf:cxf-rt-$it:$cxfVersion") { transitive false}
}
jbossmodules 'org.apache.geronimo.bundles:commons-httpclient:3.1_2'
jbossmodules 'org.apache.neethi:neethi:3.0.3'
jbossmodules 'org.apache.ws.xmlschema:xmlschema-core:2.2.1'
jbossmodules 'javax.xml.bind:jaxb-api:2.3.1'
jbossmodules 'org.glassfish.jaxb:jaxb-runtime:2.3.1'
jbossmodules 'wsdl4j:wsdl4j:1.6.3'
//jbossmodules 'javax.servlet:jstl:1.0.6'
jbossmodules 'org.mozilla:rhino:1.7.7'
libs.each {
add('jbossmodules', it.value.dependency, it.value.options)
}
jbossmodules project(path: ":RegedCommon", configuration: "java8LoggerModule")
if (appEnv != dev) {
moduleProjects.each {
jbossmodules (project(":$it")) {transitive = false}
}
}
jbossmodules 'bsf:bsf:2.3.0'
buildProject project(':Build')
}
if (appEnv != ci) {
jbossrepos {
'regedlib.modules' {
version = V_1_1
}
}
modules {
reged {
moduleName = "regedlib"
resources = configurations.jbossmodules.findAll{!it.name.startsWith('validation-api') && !projArts.contains(it) && !it.name.startsWith('log4j-1') && !it.name.contains('java8LoggerModule')}.collect{it.name}
if (appEnv == dev) {
resourceFiles = [project(':Common').file('./target/classes').absolutePath, project(':Common').file('./target/classes/Workpoint').absolutePath]
resourceFiles += moduleProjects.collect{file("$it/target/classes").absolutePath}
} else {
resourceFiles = ['../../classes', '../../classes/Workpoint']
}
dependencies = [
[name: "javax.api", export: "true"],
[name: "javax.activation.api", export: "true"],
[name: "javax.annotation.api", export: "true"],
[name: "javax.mail.api", export: "true"],
[name: "javax.resource.api", export: "true"],
[name: "javax.servlet.api", export: "true"],
[name: "javax.servlet.jsp.api", export: "true"],
[name: "javax.servlet.jstl.api", export: "true"],
[name: "javax.ejb.api", export: "true"],
[name: "javax.jms.api", export: "true"],
[name: "javax.jws.api", export: "true"],
[name: "javax.validation.api", export: "true"],
[name: "javax.xml.ws.api", export: "true"],
[name: "sun.jdk", export: "true"],
[name: "org.jboss.vfs", export: "true"],
[name: "org.jboss.logmanager", export: "true"],
[name: "org.apache.log4j", export: "true"],
[name: "org.picketbox", export: "true"],
[name: "org.jboss.jboss-transaction-spi", export: "true"],
}
regedJDK8 {
moduleName = "regedlib.java8"
if (appEnv == dev) {
resourceFiles = [project(':Common').file('./target/classes').absolutePath]
} else {
resourceFiles = ['../../../classes']
}
}
inet {
moduleName = "com.inet"
resources = ["Merlia.jar"]
dependencies = [
[name: "javax.api", export: "true"],
[name: "javax.transaction.api", export: "true"]
]
configuration = configurations.jdbc
}
postgres {
moduleName = "org.postgres"
resources = ["postgresql-9.4.1209.jar"]
dependencies = [
[name: "javax.api", export: "true"],
[name: "javax.transaction.api", export: "true"]
]
configuration = configurations.jdbc
}
datadirect {
moduleName = "com.datadirect"
resources = ["greenplum.jar"]
dependencies = [
[name: "javax.api", export: "true"],
[name: "javax.transaction.api", export: "true"]
]
configuration = configurations.jdbc
}
microsoft {
moduleName = 'com.microsoft'
resources = ['sqljdbc4.jar']
dependencies = [
[name: "javax.api", export: "true"],
[name: "javax.transaction.api", export: "true"]
]
configuration = configurations.jdbc
}
java8LoggerMoudle {
moduleName = "java8.logger"
resources = ["RegedCommon-${currentVersion}-${buildNumber}-java8LoggerModule.jar","spring-core-${springframeworkVersion}.jar","slf4j-api-1.7.26.jar", "log4j-slf4j-impl-2.17.1.jar"
,"log4j-core-2.17.1.jar", "log4j-api-2.17.1.jar", "jackson-dataformat-xml-2.10.5.jar", "jackson-core-2.10.5.jar","jackson-databind-2.10.5.jar","jackson-annotations-2.10.5.jar"]
if (appEnv == dev) {
resourceFiles = [project(':Common').file('./target/classes').absolutePath]
} else {
resourceFiles = ['../../../classes']
}
dependencies = [
[name: "org.picketbox", export: "true"],
[name: "org.jboss.logmanager", export: "true"],
[name: "org.apache.log4j", export: "true"],
[name: "javax.resource.api", export: "true"]
]
}
}
makeModules.outputs.upToDateWhen { false }
}
if (doDeploy) {
if (appEnv == ci)
build.finalizedBy makeModules
}
gradle.useLogger(new TimestampEventLogger())
class TimestampEventLogger implements TaskExecutionListener {
def timestamp = 0L
public void beforeExecute(Task task) {
println "> $task.project.name:$task.name start"
timestamp = System.currentTimeMillis()
}
public void afterExecute(Task task, TaskState state) {
def elapsed=(System.currentTimeMillis()-timestamp)/1000F
println "> $task.project.name:$task.name [$elapsed]"
}
}
evaluationDependsOn(':Build')
if (appEnv != ci) {
afterEvaluate {
distributions {
main {
baseName = 'Trax'
contents {
into ('/') {
subprojects {
if (it.name in webProjects) {
from project(it.path).distZip
}
}
from tasks['regedlib.modulesDistZip']
from (project(':').file('CCMS')) {
include 'ccms/**/*.*'
include 'perlLib/*.pm'
filesMatching('**/version.properties') {
filter ReplaceTokens, tokens: [
"version.num": buildNumber.toString(),
"version.date": versionDate,
"version.label": versionLabel
]
}
}
}
into ("/database/999_APP_VERSION/DataScripts") {
from project(":Build").file('templates')
include 'AppVersionUpdateTemplate.sql'
rename('AppVersionUpdateTemplate.sql', "AppVersionUpdate_${version}.sql")
filter(ReplaceTokens, tokens: ['app.version':version])
}
}
}
source {
baseName = 'Trax'
contents {
into ('/') {
from subprojects.findAll {!(it.getPath().startsWith(":wpServices")) && it.name != 'Common'}.sourcesJar
from (project(':').file('CCMS')) {
include 'ccms/**/*.*'
include 'perlLib/*.pm'
filesMatching('**/version.properties') {
filter ReplaceTokens, tokens: [
"version.num": buildNumber.toString(),
"version.date": versionDate,
"version.label": versionLabel
]
}
}
}
into ('/Common') {
from ('Common/src/main/resources') {
filesMatching('**/regedcommon.properties') {
filter {String line ->
line.replaceAll("(?i)(.*password=).*", "\$1")
.replaceAll("(?i)(jboss.passphrase=).*", "\$1")
.replaceAll("(?i)(tapesty.serialization.hmac.key=).*", "\$1")
.replaceAll("(?i)(jboss.algorithm=).*", "\$1")
}
}
}
}
}
}
}
sourceDistZip {
archiveClassifier = "src"
}
}
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact "$buildDir/distributions/regedlib.modules-${version}.tgz"
artifactId 'regedlib.modules'
}
}
}
artifactory {
contextUrl = artifactoryContextUrl
publish {
repository {
repoKey = artifactoryRepoKey // The Artifactory repository key to publish to
username = artifactoryUsername // The publisher user name
password = artifactoryPassword // The publisher password
}
defaults {
publications('mavenJava')
publishArtifacts = true
publishPom = true
}
}
}
task testReport(type: TestReport) {
destinationDir = file("$buildDir/reports/allTests")
// Include the results from the 'test' task in all subprojects
//reportOn subprojects*.test
reportOn subprojects.findAll {!(it.getPath().startsWith(":wpServices"))}.test
}
test {
useJUnitPlatform()
finalizedBy jacocoTestReport
}
jacoco {
toolVersion = "0.8.5"
reportsDir = file("${project.buildDir}/reports/jacoco/jacoco")
}
jacocoTestReport {
reports {
xml.enabled true
html.enabled true
csv.enabled false
xml.destination file("${project.buildDir}/reports/jacoco/test/jacocoTestReport.xml")
html.destination file("${project.buildDir}/reports/jacoco/test/html")
}
dependsOn tasks.build
}
sonarqube {
properties {
property "sonar.java.codeCoveragePlugin", "jacoco"
property "sonar.junit.reportPaths", "${project.buildDir}/reports/jacoco/test"
property "sonar.sourceEncoding", "UTF-8"
property "sonar.projectName", "TRAX"
// property "sonar.jacoco.reportsPaths", "${project.buildDir}/reports/jacoco/test"
property "sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/jacoco/test/jacocoTestReport.xml"
}
}
tasks.sonarqube.dependsOn test
I have a Java+Kotlin application, building with Gradle.
Some of its low-level functionality is provided by a separate C++ application.
The two applications communicate via a socket or pipe, using Protocol Buffers and gRPC.
Initially, I'd hoped to build all three (ProtoBuf generated code, Java application, C++ application) in one project, however the cpp-application and java conflict over certain tasks (compile/implementation/test?).
I've since split this into three projects:
/
build.gradle
settings.gradle
cpp-app/
build.gradle
settings.gradle
...
java-app/
build.gradle
settings.gradle
...
protocol/
build.gradle
settings.gradle
build/generated/source/proto/main/java/... <-- Java generated code
build/generated/source/proto/main/cpp/... <-- C++ generated code
...
I have the protocol project successfully generating C++ and Java implementations.
How do I get the C++ and Java application projects to resolve and to use these outputs in their builds?
I solved this while I was writing the question.
The gradle configuration files are shown below. There are a couple redundant blocks which are not needed for this example (or needed at all), however they achieve the objective.
/build.gradle
subprojects {
group = 'com.whatever.your.group'
version = '0.0.0'
repositories {
mavenCentral()
}
}
/settings.gradle
rootProject.name = 'my-project'
include 'java-app'
include 'cpp-app'
include 'protocol'
/java-app/build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.20"
}
}
plugins {
// Java
id 'maven'
id 'idea'
id 'application'
id 'java'
id 'org.jetbrains.kotlin.jvm' version '1.3.20'
// ProtoBuf
id 'com.google.protobuf' version '0.8.8'
}
description = """"""
sourceCompatibility = 8
targetCompatibility = 8
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
mainClassName = 'my.main.Class'
dependencies {
protobuf project(':protocol') // <-- name of protobuf project
compile project(':protocol') // <-- name of protobuf project
// We have "protobuf" and "compile", as "compile" brings in transitive dependencies
testCompile 'junit:junit:4.12'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.20"
testImplementation "org.jetbrains.kotlin:kotlin-test:1.3.20"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit:1.3.20"
}
sourceSets {
main {
java {
srcDir "src/main/java"
}
kotlin {
srcDir "src/main/kotlin"
}
}
}
/java-app/settings.gradle
rootProject.name = 'java-app'
/cpp-app/build.gradle
plugins {
id 'maven'
id 'cpp'
}
description = """"""
project.tasks.build.dependsOn 'protocol' // <-- name of protobuf project
model {
components {
main(NativeExecutableSpec) {
...
}
}
...
}
/cpp-app/settings.gradle
rootProject.name = 'cpp-app'
/protocol/build.gradle
plugins {
id 'maven'
id 'java'
id 'com.google.protobuf' version '0.8.8'
}
repositories {
mavenCentral()
}
description = """"""
sourceCompatibility = 8
targetCompatibility = 8
dependencies {
compile 'com.google.protobuf:protobuf-java:3.7.0'
compile 'io.grpc:grpc-stub:1.19.0'
compile 'io.grpc:grpc-protobuf:1.19.0'
}
sourceSets {
main {
proto {
srcDir "src/main/proto"
}
}
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.7.0"
}
plugins {
grpc_java {
artifact = 'io.grpc:protoc-gen-grpc-java:1.19.0'
}
grpc_cpp {
path = getPluginPath('cpp')
}
grpc_python {
path = getPluginPath('python')
}
}
generateProtoTasks {
generatedFilesBaseDir = "${buildDir}/build/generated/src"
all()*.builtins {
java { }
cpp { }
python { }
}
all()*.plugins {
grpc_java {
outputSubDir = 'java'
}
grpc_cpp {
outputSubDir = 'cpp'
}
grpc_python {
outputSubDir = 'python'
}
}
}
}
clean {
delete protobuf.generatedFilesBaseDir
}
// Used to find executables for generating C++ and Java gRPC
static def getPluginPath(name) {
def path = "which grpc_${name}_plugin".execute()
path.waitFor()
path = path.in.text.trim()
if (!path) {
println "Failed to locate GRPC plugin for ${name}"
} else {
println "Found GRPC plugin for ${name} at ${path}"
}
return path
}
/protocol/settings.gradle
rootProject.name = 'protocol'
Then in the project root, I can run gradle assemble, and:
$ gradle assemble
> Configure project :protocol
Found GRPC plugin for cpp at /usr/bin/grpc_cpp_plugin
Found GRPC plugin for python at /usr/bin/grpc_python_plugin
> Task :cpp-app:linkMainExecutable NO-SOURCE
> Task :cpp-app:mainExecutable UP-TO-DATE
> Task :cpp-app:assemble UP-TO-DATE
> Task :protocol:extractIncludeProto
> Task :protocol:extractProto
> Task :protocol:generateProto
> Task :protocol:compileJava
> Task :protocol:processResources
> Task :protocol:classes
> Task :protocol:jar
> Task :protocol:assemble
> Task :java-app:extractIncludeProto
> Task :java-app:extractProto
> Task :java-app:generateProto
> Task :java-app:compileKotlin
> Task :java-app:compileJava
> Task :java-app:processResources
> Task :java-app:classes
> Task :java-app:inspectClassesForKotlinIC
> Task :java-app:jar
> Task :java-app:startScripts
> Task :java-app:distTar
> Task :java-app:distZip
> Task :java-app:assemble
BUILD SUCCESSFUL in 10s
17 actionable tasks: 17 executed
I created a jar, added a main class and ran it using java -jar. This executes normally, but when I upload it to AWS Lambda, I get the following:
{
"errorMessage": "Error loading class com.me.MyHandler:com/google/api/client/googleapis/json/GoogleJsonResponseException",
"errorType": "class java.lang.NoClassDefFoundError"
}
Here's the log output:
Error loading class com.me.MyHandler: com/google/api/client/googleapis/json/GoogleJsonResponseException: class java.lang.NoClassDefFoundError
java.lang.NoClassDefFoundError: com/google/api/client/googleapis/json/GoogleJsonResponseException
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
Caused by: java.lang.ClassNotFoundException: com.google.api.client.googleapis.json.GoogleJsonResponseException
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 2 more
I unzipped the jar and found GoogleJsonResponseException.class. Is something weird in AWS's execution environment? Even if I don't use Google's exception, I seem to be getting errors with every Google class.
Here's the build.gradle file
group 'com.me'
version '1.0.1'
apply plugin: 'java'
apply plugin: 'application'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile group: 'com.amazonaws', name: 'aws-lambda-java-core', version: '1.1.0'
compile group: 'com.amazonaws', name: 'aws-lambda-java-log4j', version: '1.0.0'
compile group: 'com.google.api-client', name: 'google-api-client', version: '1.22.0'
compile group: 'log4j', name: 'log4j', version: '1.2.17'
compile group: 'com.google.apis', name: 'google-api-services-customsearch', version: 'v1-rev54-1.22.0'
compile group: 'com.google.http-client', name: 'google-http-client-gson', version: '1.22.0'
compile group: 'com.google.http-client', name: 'google-http-client', version: '1.22.0'
compile group: 'com.google.api-client', name: 'google-api-client', version: '1.22.0'
compile group: 'commons-io', name: 'commons-io', version: '2.5'
compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.0.1'
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile group: 'org.assertj', name: 'assertj-core', version: '3.6.2'
runtime 'com.google.api-client:google-api-client:1.22.0'
}
mainClassName = "com.me.Main"
jar {
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
manifest {
attributes 'Main-Class': mainClassName
}
}
Here's the main method:
public class Main {
public static void main(String[] args) {
System.out.println("starting main");
MyHandler myHandler = new MyHandler();
myHandler.handleRequest(null, null);
}
}
Here's the code calling Google's lib:
public class MyHandler implements
RequestHandler<Map, String> {
static final Logger log = Logger.getLogger(MyHandler.class);
#Override
public String handleRequest(Map input, Context context) {
log.info("Handling request.");
try {
log.info("Initializing custom search");
Customsearch.Builder builder = new Customsearch.Builder(
GoogleNetHttpTransport.newTrustedTransport(),
new GsonFactory(),
null);
builder.setGoogleClientRequestInitializer(new CustomsearchRequestInitializer("test"));
builder.setApplicationName("testQuery");
Customsearch customsearch = builder.build();
Customsearch.Cse.List list = customsearch.cse().list("test");
list.setKey("test");
list.setCx("test");
Search results;
try {
results = list.execute();
} catch (GoogleJsonResponseException gjre) {
log.error(gjre.getMessage());
throw gjre;
}
} catch (IOException e) {
e.printStackTrace();
} catch (GeneralSecurityException gse) {
gse.printStackTrace();
}
return "test";
}
}
I cut a support ticket to AWS and found a way around the issue. Looks like the fat jar step didn't fully package everything. Instead, they suggested uploading a build zip (add this to end of gradle file):
task buildZip(type: Zip) {
from compileJava
from processResources
into('lib') {
from configurations.runtime
}
}
I added that and uploaded the zip instead of the jar. Worked just fine.
I have a Gradle project configured with jacoco plugin to report the test code coverage. My unit tests are written in Spock framework.
Though the Jacoco plugin generates the HTML report, it reports the code coverage as 0% on all classes.
I googled a lot and couldn't find what I'm missing. Has anyone got the Spock code coverage working with Gradle + Jacoco?
apply plugin: "jacoco"
apply plugin: "groovy"
sourceSets {
main {
java { srcDirs = ['src/main/java'] }
groovy {srcDirs = ['src/main/groovy'] }
resources { srcDir 'src/main/resources' }
}
test {
java { srcDirs = ['src/test/java'] }
groovy { srcDirs = ['src/test/groovy'] }
resources { srcDir 'src/test/resources' }
}
}
test {
jvmArgs '-Xms64m', '-Xmx2G', '-XX:MaxPermSize=128m'
}
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
html.destination "${buildDir}/jacocoHtml"
}
}
dependencies {
testCompile "org.spockframework:spock-core:0.7-groovy-2.0"
testCompile "org.spockframework:spock-spring:0.7-groovy-2.0"
}
Suggestion from #PeterNiederwieser worked perfectly. Here is the final result:
apply plugin: "groovy"
apply plugin: "jacoco"
repositories { mavenCentral() }
dependencies {
compile "org.codehaus.groovy:groovy-all:2.2.2"
testCompile "org.spockframework:spock-core:0.7-groovy-2.0"
}
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
html.destination "${buildDir}/jacocoHtml"
}
}
I want to make test of some clases in my project.
I'm project is all android, but the new clases are pure Java (I'm trying to make a little sdk for the app)
But I don't know how to configure correctly
Gradle file:
apply plugin: 'android'
android {
compileSdkVersion "Google Inc.:Google APIs:19"
buildToolsVersion "19.0.1"
lintOptions{
checkReleaseBuilds false
}
defaultConfig {
minSdkVersion 8
targetSdkVersion 19
versionCode 28
versionName "4.0.5"
}
signingConfigs {
debug {
..........
}
release {
..........
}
}
buildTypes {
debug{
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
debuggable true
buildConfigField "boolean", "LOG_ENABLED", "true"
signingConfig signingConfigs.debug
}
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
debuggable false
buildConfigField "boolean", "LOG_ENABLED", "false"
signingConfig signingConfigs.release
}
}
productFlavors{
develFlavor{
}
testFlavor{
..........
}
trainingFlavor{
..........
}
preFlavor{
..........
}
proFlavor{
.........
}
}
}
if (project.hasProperty('storePassword')) {
android.signingConfigs.release.storePassword = storePassword
}
if (project.hasProperty('keyAlias')) {
android.signingConfigs.release.keyAlias = keyAlias
}
if (project.hasProperty('keyPassword')) {
android.signingConfigs.release.keyPassword = keyPassword
}
repositories {
mavenCentral()
}
sourceSets {
test {
java.srcDir file(''src/main/java/es/tempos/gas/sdk/test'')
}
}
dependencies {
unitTestCompile 'junit:junit:4.11'
compile 'com.google.code.gson:gson:1.7.1'
compile 'com.android.support:appcompat-v7:+'
compile files('libs/libGoogleAnalyticsServices.jar')
compile files('libs/sbc_mapslib.jar')
compile files('libs/t21c2dm-lib-v1.0.jar')
}
I want to put the test cases in the folfer Test>SDK
Estructure of the app:
+SmartPhoneGreatApp
----.idea
----app
-----build
-----libs
-----src
-----develFlavor
-----main
----sdk
-----preFlavor
----- .........
........
-----test
------sdk
and the testing class(for the moment do nothing)
package es.tempos21.gas.sdk.test;
import org.junit.Test;
public class AuthenticateTest {
#Test
public void testAuthenticate() throws Exception {
}
}
And the error I'm getting:
Gradle 'SmartPhoneGreatApp' project refresh failed:
Could not find property 'unitTest' on SourceSet container.
Gradle settings
In the Android plugin, sourceSets are configured differently from how the Java plugin does it, so you should read the docs at http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Sourcesets-and-Dependencies
For testing you'll want to do something like this:
android {
sourceSets {
androidTest.setRoot('tests')
}
}
A shortcut would be to do this instead:
android.sourceSets.androidTest.setRoot('tests')
Note that you're supplying a new top-level directory for where the tests go (and the Java classes will be in a directory structure underneath that corresponds to their package path); in your example you're trying to point it at a package already inside src/main/java/path/to/package, which isn't going to work.