How to use scoverage with Flink shadowjar custom gradle dependency configuration - build.gradle

Summary
I've got a Gradle Flink Scala project and am trying to add Scoverage reports, but the compileScoverageScala task can't find all the dependencies due to the custom shadow jar configuration.
build.gradle
Here's the build file, which follows Flink's Gradle example. The only difference is I've tried to add Scoverage.
// Here are the plugins I'm using
plugins {
id 'scala'
id 'application'
// shadow plugin to produce fat JARs
id 'com.github.johnrengelman.shadow' version '5.2.0'
id "org.scoverage" version "4.0.1"
id "com.github.maiflai.scalatest" version "0.25"
}
...
// Here's the custom configuration used to build the shadow jar without including the main Flink libraries
configurations {
flinkShadowJar // dependencies which go into the shadowJar
// always exclude these (also from transitive dependencies) since they are provided by Flink
flinkShadowJar.exclude group: 'org.apache.flink', module: 'force-shading'
flinkShadowJar.exclude group: 'com.google.code.findbugs', module: 'jsr305'
flinkShadowJar.exclude group: 'org.slf4j'
flinkShadowJar.exclude group: 'log4j'
}
...
// Here's where the custom configuration is added to the classpath, Scoverage isn't picking these up.
sourceSets {
main.compileClasspath += configurations.flinkShadowJar
main.runtimeClasspath += configurations.flinkShadowJar
test.compileClasspath += configurations.flinkShadowJar
test.runtimeClasspath += configurations.flinkShadowJar
javadoc.classpath += configurations.flinkShadowJar
}
Here's the build output:
$ ./gradlew clean build
> Task :compileScala
Pruning sources from previous analysis, due to incompatible CompileSetup.
> Task :compileScoverageScala FAILED
Pruning sources from previous analysis, due to incompatible CompileSetup.
/Users/david.perkins/dev/wffh/flink-validation-fhir/src/main/scala/com/ibm/watson/health/foundation/hri/flink/FhirValidationJob.scala:6: object core is not a member of package com.ibm.watson.health.foundation.hri.flink
import com.ibm.watson.health.foundation.hri.flink.core.BaseValidationJob
^
The missing package is declared as a flinkShadowJar dependency. The compileScala task is able to find it, but compileScoverageScala can't.
Anyone know if there's a way to explicitly tell Scoverage to include the flinkShadowJar configuration? I'm hoping others using Flink have run into this before and know a way to fix it.

I got some help from the Scoverage team: https://github.com/scoverage/gradle-scoverage/issues/138
Adding this to my sourceSets declaration fixed it.
scoverage.compileClasspath += configurations.flinkShadowJar
scoverage.runtimeClasspath += configurations.flinkShadowJar

Related

UnknownClass.Cucumber while running JUnit engine + Cucumber + Gradle tests from command line

Me and my team just moved from JUnit4 to JUnit5 and we faced with parallelism issues. With 4th version we used -Dcucumber.options="--threads 5" to run in tests several threads, but after deprecation and removing of cucumber options it's obviously doesn't work anymore. I set up (at least I think so) junit platform engine for the project (https://github.com/cucumber/cucumber-jvm/tree/main/cucumber-junit-platform-engine#configuration-options), but when I try to run tests via comand line (using Gradle task), I receive following error:
UnknownClass.Cucumber > UnknownClass.initializationError FAILED
org.junit.platform.commons.JUnitException at EngineExecutionOrchestrator.java:114
Caused by: org.junit.platform.commons.JUnitException at HierarchicalTestEngine.java:57
Caused by: org.junit.platform.commons.JUnitException at DefaultParallelExecutionConfigurationStrategy.java:41
Unfortunately, didn't find something in the internet, maybe someone can help with it?
What we use:
Spring boot 2.7.3
Gradle 7.5.1
Cucumber java, junit, spring, junit-platform-engine 5.7.0
junit-platform-suite-api 1.3.2
Tasks in build.gradle that I have now:
useJUnitPlatform()
systemProperty("cucumber.junit-platform.naming-strategy", "long")
systemProperty("cucumber.execution.parallel.enabled", true)
systemProperty("cucumber.execution.parallel.config.strategy", "fixed")
systemProperty("cucumber.plugin", "html:reports/html")
systemProperty("cucumber.plugin", "pretty")
systemProperty("cucumber.plugin", "junit:reports/junit")
doLast {
javaexec {
mainClass.set("io.cucumber.core.cli.Main")
classpath = cucumberRuntime + sourceSets.test.get().output + sourceSets.main.get().output
}
}
}
tasks {
val consoleLauncherTest by registering(JavaExec::class) {
dependsOn(testClasses)
val reportsDir = file("$buildDir/test-results")
outputs.dir(reportsDir)
classpath = sourceSets["test"].runtimeClasspath
mainClass.set("org.junit.platform.console.ConsoleLauncher")
args("--scan-classpath")
args("--include-engine", "cucumber")
args("--reports-dir", reportsDir)
}
test {
dependsOn(consoleLauncherTest)
exclude("**/*")
}
}
Configuration class:
#CucumberContextConfiguration
#Suite
#IncludeEngines("cucumber")
#SelectClasspathResource("com/example")
#ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.example")
#SpringBootTest
#ContextConfiguration(classes = [IntegrationContext::class], loader = SpringBootContextLoader::class)
class Application() {}
Your question is pretty much impossible to answer because you didn't go through the process of making a minimal reproducer. For your next question please read the "Help others reproduce the problem" section in How do I ask a good question?.
With 4th version we used -Dcucumber.options="--threads 5" to run in tests several threads, but after deprecation and removing of cucumber options it's obviously doesn't work anymore.
Project typically include a CHANGELOG and release notes documenting all relevant changes.
What we use:
Spring boot 2.7.3
Cucumber java, junit, spring, junit-platform-engine 5.7.0
junit-platform-suite-api 1.3.2
These dependencies don't converge and aren't quite correct. You'll want to use Cucumber's and JUnit's Bill of Materials to avoid having to specify the version for every module.
If you're using Spring Boot in the recommended way you may also be able to omit the junit-bom altogether.
dependencies {
testImplementation(platform("org.junit:junit-bom:5.9.1"))
testImplementation(platform("io.cucumber:cucumber-bom:7.9.0"))
testImplementation("io.cucumber:cucumber-java")
testImplementation("io.cucumber:cucumber-junit-platform-engine")
testImplementation("org.junit.platform:junit-platform-suite")
testImplementation("org.junit.jupiter:junit-jupiter")
}
Tasks in build.gradle that I have now:
So in this build file it appears that you are trying to run Cucumber in 3 different ways. Through the JUnit Platform, through Cucumbers CLI and through the JUnit 5 ConsoleLauncher.
I don't know which solution you are trying use but suppose that you want to use the JUnit Platform, then you look at cucumber-java-skeleton for a working example.
Then afterwards you should clean up your build file. :D

How to configure bootBuildImage task to be up-to-date when no changes to source code

I'm trying to use spring boot 2.3's new support for creating docker images, but the bootBuildImage gradle task is never up-to-date. This unfortunately causes a new docker image to be generated even if no source code was changed.
My goal is to have a static build command that doesn't result in new images being produced unnecessarily. So something like one of the two scenarios below:
./gradlew bootBuildImage (but does nothing if no source code has changed)
OR
./gradlew someOtherTask (if this task is not up-to-date, it triggers bootBuildImage)
My latest effort was to configure bootBuildImage to only run if the bootJar task is not up to date:
tasks {
val bootJarTask: TaskProvider<BootJar> = this.bootJar
bootBuildImage {
outputs.upToDateWhen {
bootJarTask.get().state.upToDate
}
}
}
But this fails with this error (for some reason this particular task hates jars as inputs)
> Unable to store input properties for task ':bootBuildImage'. Property 'jar' with value '/demo/build/libs/demo-0.0.1-SNAPSHOT.jar' cannot be serialized.
Surely I'm missing something obvious here! The reason I need bootBuildImage to only produce an image when necessary is because I've got a multi-project build. I don't want subprojects to generate and push a new image even when nothing in them changed.
Using Spring Boot 2.3.4, Gradle 6.6.1, Java 11.
This seems to work:
val bootJarTask: TaskProvider<BootJar> = this.bootJar
bootBuildImage {
onlyIf {
!bootJarTask.get().state.skipped
}
}

Can the ConfigurationAPI in Liferay DXP be used for Plugin sdk portlet?

I have followed given 2 tutorials to use COnfigurationAPI in a Liferay dxp plugins SDK portlet built using Ant/Ivy.
COnfiguration API 1
COnfiguration API 2.
Below is the configuration class used:
package com.preferences.interfaces;
import com.liferay.portal.configuration.metatype.annotations.ExtendedObjectClassDefinition;
import aQute.bnd.annotation.metatype.Meta;
#ExtendedObjectClassDefinition(
category = "preferences",
scope = ExtendedObjectClassDefinition.Scope.GROUP
)
#Meta.OCD(
id = "com.preferences.interfaces.UnsupportedBrowserGroupServiceConfiguration",
name = "UnsupportedBrowser.group.service.configuration.name"
)
public interface UnsupportedBrowserGroupServiceConfiguration {
#Meta.AD(deflt = "", required = false)
public String displayStyle();
#Meta.AD(deflt = "0", required = false)
public long displayStyleGroupId(long defaultDisplayStyleGroupId);
}
Post following the steps,I am getting the below error:
ERROR [CM Configuration Updater (ManagedService Update: pid=[com.preferences.interfaces.UnsupportedBrowserGroupServiceConfiguration])][org_apache_felix_configadmin:97] [org.osgi.service.cm.ManagedService, id=7082, bundle=297//com.liferay.portal.configuration.settings-2.0.15.jar?lpkgPath=C:\dev\Liferay\osgi\marketplace\Liferay Foundation.lpkg]: Unexpected problem updating configuration com.preferences.interfaces.UnsupportedBrowserGroupServiceConfiguration {org.osgi.service.cm.ConfigurationAdmin}={service.vendor=Apache Software Foundation, service.pid=org.apache.felix.cm.ConfigurationAdmin, service.description=Configuration Admin Service Specification 1.2 Implementation, service.id=56, service.bundleid=643, service.scope=bundle}
Caused by: java.lang.IllegalArgumentException: wrong number of arguments
So,does this process need a osgi module as mandatory or can we do it using plusings sdk portlet built using ant as well?
Without disecting the error message Caused by: java.lang.IllegalArgumentException: wrong number of arguments:
The way you build your plugin (Ant, Maven, Gradle, manually) doesn't make a difference, as long as you build a plugin that will be understood by the runtime. aQute.bnd.annotation.metatype.Meta points firmly into the OSGi world, and makes it almost certain that you'll need an OSGi module. You can build this with Ant, of course. Even in Ant you can embed tools like bnd, or you can write the proper Manifest.mf to include in your module manually (just kidding - you don't want to do it manually, but it would work).
Recommendation: Instead of moving everything over: Try to reproduce this with a minimal example in gradle or better Liferay Workspace (which is gradle based), just to get all the automatic wiring in. Check if it makes a difference and compare the generated output from your Ant build process with the workspace output. Pay specific attention to the Manifest.
In order to build the proper Manifest, you want to use bnd - if the Manifest turns out to be your issue: Find a way to embrace bnd - if that's by saying goodby to Ant, or by tweaking your build script remains your decision.

ceylon run: Module default/unversioned not found

Today i installed the intelliJ ceylon IDE on my macbook. When compiling my project I get the following message
/Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/bin/java "-Dceylon.system.repo=/Users/Laust/Library/ApplicationSupport/IdeaIC2016.3/CeylonIDEA/classes/embeddedDist/repo" -Didea.launcher.port=7533 "-Didea.launcher.bin.path=/Applications/IntelliJ IDEA CE.app/Contents/bin" -Dfile.encoding=UTF-8 -classpath "/Users/Laust/Library/Application Support/IdeaIC2016.3/CeylonIDEA/classes/embeddedDist/lib/ceylon-bootstrap.jar:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar" com.intellij.rt.execution.application.AppMain com.redhat.ceylon.launcher.Bootstrap run --run main default/unversioned
ceylon run: Module default/unversioned not found in the following repositories:
/Users/Laust/Library/Application Support/IdeaIC2016.
3/CeylonIDEA/classes/embeddedDist/repo
/Users/Laust/.ceylon/cache
https://modules.ceylon-lang.org/repo/1
[Maven] Aether
[NPM] npm
Process finished with exit code 1
The code executes fine on my other computer (windows 7).
the folder 'modules' contains the following:
default
default.car
default.car.sha1
default.src
default.src.sha1
and my build configuration looks as follows.
this is my code (in the file source/main.ceylon)
shared void main() {
print("Generating pretty sweet g-code:");
{Gcommand+} myGcommands = {
G00( Vector3(0.0, 0.0, 0.0) ),
G00( Vector3(9.0, 0.0, 0.0) ),
G00( Vector3(9.0, 9.0, 0.0) ),
G00( Vector3(0.0, 9.0, 0.0) ),
G00( Vector3(0.0, 0.0, 0.0) )
};
GcodeProgram myGcodeProgram = GcodeProgram( *myGcommands );
print(myGcodeProgram.toString());
}
"A carthesian coordinate class"
alias X => Float;
alias Y => Float;
alias Z => Float;
class Vector3(shared X x, shared Y y, shared Z z) {
}
"An abstract spec class for all G-code command classes"
abstract class Gcommand() {
shared formal String toString();
}
"G-code command for moving in a straight line at rapid speed"
class G00( Vector3 endPoint ) extends Gcommand() {
toString() => "G0 " + "X" + endPoint.x.string
+ "Y" + endPoint.y.string
+ "Z" + endPoint.z.string + "\n";
}
class GcodeProgram( Gcommand+ gcommands ) {
variable String stringifiedGcodeProgram = "";
shared String toString() {
for (gcommand in gcommands) {
stringifiedGcodeProgram = stringifiedGcodeProgram + gcommand.toString();
}
return stringifiedGcodeProgram;
}
}
The screenshot you provided shows that the run configuration isn't based on any IntelliJ module (Use classpath of module is set to [none]). This means that the configuration will not be run in your project folder where the modules directory lives. That directory contains the compiled code, and ceylon run will look for that directory when you ask it to run the default module.
Generally speaking, you should avoid creating run configurations manually. By clicking on the green arrow next to a runnable function's name, Ceylon IDE will automatically create and configure a correct run configuration.
To fix your existing run configuration, simply select the IntelliJ module that contains your code in the field labeled Use classpath of module.
See also the getting started guide for more information on how to get started with Ceylon IDE for IntelliJ.
That might be a bug with the IntelliJ plugin not handling "default" modules correctly. We tend not to use default modules much because they're more limited than regular modules.
Try creating a module and moving your code to it. THat will most likely fix the problem. If so you can then open an issue to have this bug fixed here: https://github.com/ceylon/ceylon-ide-intellij/issues/new
There appears to be something messed up in the project setup here. Note the list of repos that are being searched:
Module default/unversioned not found in the following repositories:
/Users/Laust/Library/Application Support/IdeaIC2016.3/CeylonIDEA/classes/embeddedDist/repo
/Users/Laust/.ceylon/cache
https://modules.ceylon-lang.org/repo/1
[Maven] Aether
[NPM] npm
I would expect to see a repo of form your-project-dir/modules as the second entry in that list, but it's not there.
That is to say, ceylon run is not looking in the modules directory where the compiled .car is. So the question is why that repo is missing from the list.
What do you see in Project Structure > Modules > Ceylon > Repositories?
In this question, the first (and only) answer tells how to create a new module.
I have a few comments to that answer:
when beginning on a new project, you probably don't need an intricate nested naming hierarchy for your modules. You will get that, if you use periods in your module name (eg. my.ceylon.example), so I suggest you stick to a simple name such as main.
when creating your new module, you will (among other things) be asked to specify a 'Runnable unit name'. The purpose of this field is to tell IntelliJ which of your modules' classes it should execute when starting your program. In other words, this becomes the entry point to your program. A suitable name for this could (also) be main.
Ceylon projects are divided into modules, modules are divided into packages, and packages are divided into classes and top-level functions. When you create a module, a package is automatically created under this module. The path for your code files under this module will be 'source/moduleName/packageName'. When creating a new module, you don't get to specify the name for the first package in the module. Instead the package is given the same name as your module name. Thus a module named 'main' would have this path: source/main/main as the path for it's code files.
In your new modules folder (eg. source/main/main) three new files will be created. Find the file that is named after the 'Runnable unit name' you chose earlier. Your code should go into this file. Also, your code should have a class with the exact same name that you chose as your 'Runnable unit name'.
the answer used the fancy term 'runnable unit', by which he just means a file containing Ceylon code.
remember to delete the file containing your old 'default' module, before trying to run your new module.
a module name cannot start with a capital letter.
modules/ is the output directory where compiled code goes. It is automatically recreated from the code in source/ when the project is built.

Gradle reports BUILD SUCCESSFUL, however I can not locate any .class files

I am attempting to use Gradle (for the first time) for a multiproject java build.
I have created a settings.gradle file with all the project names. I have also create a very basic build.gradle file. To my surprise when I run gradle build. It returns BUILD SUCCESSFUL. Jars are created in the build\libs folder. What is puzzling to me is that no .class files exists. Also I have been unable to get any kind of Junit results or xml output.
I'm wondering if this is really building correctly. For now this is my very basic build.gradle file. Any input is appreciated, thanks.
subprojects {
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
version = '1.0'
compileJava.destinationDir = file("$buildDir/output/classes")
repositories {
}
dependencies {
}
test {
testLogging {
exceptionFormat 'full'
events 'started', 'passed', 'skipped', 'failed', 'standardOut', 'standardError'
}
}
jar {
manifest.attributes provider: 'gradle'
}
}
As requested this is my project directory structure.
MainProject
build.gradle
settings.gradle
--SubProject1
----src
--Subproject2
----src
.
.
.
Make sure your subprojects are laid out according to the defaults for the Java plugin
( see section 23.4 Project Layout in http://www.gradle.org/docs/current/userguide/java_plugin.html)
or tell the plugin where you have put things
( see section 23.4.1. Changing the project layout )