why "jar.enabled = false" affects dependencies in Gradle? - gradle

The story:
I have recently discovered that setting jar.enabled = false in project b-features of a multi-projects Gradle project will stop project a-features of the same project from being able to refer to B via
dependencies {
compile project(':b-features')
}
The question:
Why is jar.enabled = false stopping project A from successfully referring to project B?
Additional info:
build.gradle of the root project:
group 'gradle.studies'
apply plugin: 'java'
...
settings.gradle of the root project:
rootProject.name = 'multi-project-reference'
include 'a-features'
include 'b-features'
build.gradle of the project a-features:
group 'gradle.studies'
apply plugin: 'java'
...
dependencies {
compile project(':b-features')
}
...
build.gradle of the project b-features
group 'gradle.studies'
apply plugin: 'java'
jar.enabled = false
...
Class A in a-features project:
package outerproject;
import innerproject.B;
public class A {
public static void main(String[] args) {
B b = new B();
System.out.println(b.getMsg());
}
}
Class B in b-features project:
package innerproject;
public class B {
public B() {
this.msg = "Hello World";
}
private String msg;
public String getMsg() {
return msg;
}
//...
}
The error:
14:27:50: Executing external task 'build'...
:compileJava NO-SOURCE :processResources NO-SOURCE :classes UP-TO-DATE
:jar UP-TO-DATE :assemble UP-TO-DATE :compileTestJava NO-SOURCE
:processTestResources NO-SOURCE :testClasses UP-TO-DATE :test
NO-SOURCE :check UP-TO-DATE :build UP-TO-DATE :b-features:compileJava
UP-TO-DATE :b-features:processResources NO-SOURCE :b-features:classes
UP-TO-DATE :b-features:jar SKIPPED
/home/nikita/IdeaProjects/multi-project-reference/a-features/src/main/java/outerproject/A.java:3:
error: package innerproject does not exist import innerproject.B;
^ /home/nikita/IdeaProjects/multi-project-reference/a-features/src/main/java/outerproject/A.java:7:
error: cannot find symbol
B b = new B();
^ symbol: class B location: class A /home/nikita/IdeaProjects/multi-project-reference/a-features/src/main/java/outerproject/A.java:7:
error: cannot find symbol
B b = new B();
^ symbol: class B location: class A 3 errors :a-features:compileJava FAILED
FAILURE: Build failed with an exception.

What you actually depend on, is the artifact (JAR file) that is produced by the project. As you disabled the generation of the artifact (jar task), the needed classes of course are not found any longer.

Related

Configure Zip/Copy Task in a Plugin with Gradle

I am trying to create an Zip task in a plugin:
class MyPlugin implements Plugin<Project> {
#Override
void apply(Project project) {
Zip buildFunctionArchive = project.tasks.create("buildFunctionArchive", Zip.class) {
archiveClassifier = "yolo"
from(project.getTasksByName("compileJava", true))
}
}
}
But for some reason even though the compileJava task exists in the project form which I use my plugin. When I print debug output I get: NO-SOURCE
2020-10-05T02:16:03.565+1100 [LIFECYCLE] [class org.gradle.internal.buildevents.TaskExecutionLogger] > Task :buildFunctionArchive NO-SOURCE
If I configure the from in my client project:
buildFunctionArchive{
from compileJava
}
This works, and I even see the yolo in the archive name. But if I remove the from compileJava
buildFunctionArchive{
}
As well as removing the configuration all together and running gradle buildFunctionArchive
The task will not create the archive, even though I have configured this in the MyPlugin class, I will get the NO-SOURCE error. What am I missing? I am wanting to define a Zip task in my plugin but am having no luck.

TestFX Spock Gradle Project Openjdk 11 - Zero Test Results

Why is my Spock test not executed and I get zero test results when I execute:
./gradlew clean test
with my TestFX Spock Gradle Project with Openjdk 11?
Here's the zero test results:
My Spock test class gets compiled OK but not executed.
Here's my console:
Working Directory: /home/~/EclipseProjects/gradleTestfxSpock
Gradle user home: /home/~/.gradle
Gradle Distribution: Gradle wrapper from target build
Gradle Version: 5.0
Java Home: /usr/lib/jvm/jdk-11.0.2+9
JVM Arguments: None
Program Arguments: None
Build Scans Enabled: false
Offline Mode Enabled: false
Gradle Tasks: clean test
> Configure project :
Found module name 'mtd'
> Task :clean
> Task :compileJava
> Task :compileGroovy NO-SOURCE
> Task :processResources
> Task :classes
> Task :compileTestJava NO-SOURCE
> Task :compileTestGroovy
> Task :processTestResources
> Task :testClasses
> Task :test
BUILD SUCCESSFUL in 6s
6 actionable tasks: 6 executed
Here's my build.gradle:
plugins {
id 'org.openjfx.javafxplugin' version '0.0.7'
id 'application'
id 'groovy'
}
mainClassName = 'mtd/gradleTestfxSpock.Main'
sourceCompatibility = 11
targetCompatibility = 11
repositories {
jcenter()
}
dependencies {
implementation 'org.testfx:testfx-spock:4.0.15-alpha'
testCompile 'org.testfx:testfx-core:4.0.15-alpha'
testCompile (group: 'org.spockframework', name: 'spock-core', version: '1.3-groovy-2.5')
testCompile ('org.codehaus.groovy:groovy-all:2.5.6')
testRuntime(
'com.athaydes:spock-reports:1.2.7',
'cglib:cglib-nodep:3.2.4'
)
}
javafx {
version = "11.0.2"
modules = [ 'javafx.controls',
'javafx.fxml',
'javafx.web'
]
}
compileJava {
doFirst {
options.compilerArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'javafx.controls',
'--add-modules', 'javafx.fxml',
'--add-modules', 'javafx.web'
]
}
}
test {
doFirst {
jvmArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'ALL-MODULE-PATH',
'--add-exports', 'javafx.graphics/com.sun.javafx.application=org.testfx'
]
}
}
Here's my module-info.java:
module mtd {
requires javafx.controls;
requires javafx.fxml;
requires transitive javafx.graphics;
requires javafx.web;
requires org.testfx;
requires testfx.spock;
opens gradleTestfxSpock to javafx.graphics;
exports gradleTestfxSpock;
}
Here's my Spock test code:
package gradleTestfxSpock;
import org.testfx.framework.spock.ApplicationSpec;
import javafx.stage.Stage
public class MainTest extends ApplicationSpec{
def "Main Test 01"() {
expect:
println("you are in Main test 01");
}
#Override
public void start(Stage arg0) throws Exception {
// TODO Auto-generated method stub
}
}
Here's my JavaFX code:
package gradleTestfxSpock;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("/fxml/sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
and controller:
package gradleTestfxSpock;
public class Controller {
}
Here's my eclipse gradle project structure:
In other eclipse gradle projects I have successfully executed a TestFX Junit4 test without Spock:
and separately I have successfully executed the same Spock Test without TestFX and without JUnit:
I did notice some warnings on this Spock test:
Working Directory: /home/~/EclipseProjects/gradleSpock
Gradle user home: /home/~/.gradle
Gradle Distribution: Gradle wrapper from target build
Gradle Version: 5.0
Java Home: /usr/lib/jvm/jdk-11.0.2+9
JVM Arguments: None
Program Arguments: None
Build Scans Enabled: false
Offline Mode Enabled: false
Gradle Tasks: clean test
> Task :clean
> Task :compileJava
> Task :compileGroovy NO-SOURCE
> Task :processResources NO-SOURCE
> Task :classes
> Task :compileTestJava NO-SOURCE
> Task :compileTestGroovy
> Task :processTestResources NO-SOURCE
> Task :testClasses
> Task :test
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/home/dm/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.6/6936e700f0fb1b50bac0698ada4347a769d40199/groovy-2.5.6.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
BUILD SUCCESSFUL in 9s
4 actionable tasks: 4 executed
Conclusion
If TestFX with JUnit works, and Spock alone works, but TestFX with Spock doesn't work then is there something wrong with configuring:
'org.testfx:testfx-spock:4.0.15-alpha'
Any ideas or help greatly appreciated.
ps Forgot to say that I also created the TestFX/Spock project in Netbeans duplicating the eclipse project, and I got the same result!
More Tests
More combinations of testing following Leonard Bruenings very good suggestions in comments below unfortunately didn't work.
My amended module-info.java looks like:
module mtd {
requires javafx.controls;
requires javafx.fxml;
requires transitive javafx.graphics;
requires javafx.web;
requires org.testfx.junit;
requires org.testfx;
requires testfx.spock;
requires spock.core;
requires junit;
opens gradleTestfxSpock to javafx.graphics, org.testfx, testfx.spock, spock.core, junit, org.testfx.junit;
exports gradleTestfxSpock;
}
And I added this to my gradle.build dependencies just in case:
implementation 'org.testfx:testfx-junit:4.0.15-alpha'
Still no joy...
Solution
I found that this plugin was the problem and was stopping successful execution of my Spock test:
`plugins {
id 'org.openjfx.javafxplugin' version '0.0.7'
}`
When I removed it from my build.gradle my TestFX Spock test worked OK.
With this reworked build.gradle and module-info.java I can successfully execute my Spock test:
plugins {
id 'application'
id 'groovy'
}
ext {
moduleName = "mtd"
mainQualifiedClassName = "gradleTestfxSpock.Main"
}
application {
mainClassName = "$moduleName/$mainQualifiedClassName"
}
sourceCompatibility = 11
targetCompatibility = 11
repositories {
jcenter()
}
dependencies {
implementation("org.openjfx:javafx-fxml:11:linux")
implementation("org.openjfx:javafx-web:11:linux")
implementation("org.openjfx:javafx-media:11:linux")
implementation("org.openjfx:javafx-base:11:linux")
implementation("org.openjfx:javafx-graphics:11:linux")
implementation("org.openjfx:javafx-controls:11:linux")
testImplementation ('org.testfx:testfx-spock:4.0.15-alpha')
testImplementation ('org.testfx:testfx-core:4.0.15-alpha')
testImplementation (group: 'org.spockframework', name: 'spock-core', version: '1.3-groovy-2.5')
testImplementation ('org.codehaus.groovy:groovy-all:2.5.6')
testRuntimeOnly (
'com.athaydes:spock-reports:1.2.7',
'cglib:cglib-nodep:3.2.4'
)
}
compileJava {
doFirst {
options.compilerArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'javafx.controls',
'--add-modules', 'javafx.fxml',
'--add-modules', 'javafx.web'
]
}
}
run {
doFirst {
jvmArgs = [
'--module-path', classpath.asPath,
'--patch-module', "$moduleName=" + files(sourceSets.main.output.resourcesDir).asPath,
'--module', mainClassName
]
}
}
I needed to add into the run section of the build.gradle:
'--module', mainClassName
-so that the mainClassName can be found
'--patch-module', "$moduleName=" + files(sourceSets.main.output.resourcesDir).asPath
-to provide access to resource files eg getClass().getResource("/fxml/sample.fxml")
module mtd {
requires javafx.controls;
requires javafx.fxml;
requires transitive javafx.graphics;
requires javafx.web;
exports gradleTestfxSpock;
}
I'm no expert in any of this, which is probably why it's taken me ages and ages to get to this point, but FWIW I thought I might just mention that I have managed to get it working: by "it" I mean: Java 11, JavaFX, TestFX-Spock, and using the javafxplugin. One guy who helped me, José Pereda, appears to recommend using it if you can. So I just thought I'd show my files stripped down to the bare minimum. There's no module-info.java, and I'm using Groovy for my app code as well as for Spock and Gradle.
(stripped-down) build.gradle:
plugins {
id 'java-library'
id 'groovy'
id 'eclipse'
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.8'
}
repositories {
mavenCentral()
}
dependencies {
api 'org.apache.commons:commons-math3:3.6.1'
implementation 'com.google.guava:guava:27.0.1-jre'
// although not using JUnit I think it's best to leave this line
// (included at start by Gradle):
testImplementation 'junit:junit:4.12'
implementation 'org.codehaus.groovy:groovy-all:2.5.8'
testImplementation 'org.spockframework:spock-core:1.2-groovy-2.5'
testImplementation 'org.testfx:testfx-spock:4.0.15-alpha'
}
mainClassName = 'core.App'
group 'Project'
version '1.0'
sourceCompatibility = 11
javafx {
version = "13"
modules = [ "javafx.controls", "javafx.fxml" ]
}
src/main/groovy/core/main.groovy:
package core
// (imports omitted)
public class App extends Application {
void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"))
primaryStage.title = "Hello World"
primaryStage.scene = new Scene(root, 300, 275)
primaryStage.show()
}
def main(String[] args) {
launch( App.class, args)
}
}
class Controller {
#FXML
TextField inputField
#FXML
Label label
#FXML
Button applyButton
public void applyButtonClicked () {
label.text = inputField.text
}
}
src/test/groovy/core/test.groovy:
package core
// (imports omitted)
class FuncSpec extends ApplicationSpec {
void init() throws Exception {
FxToolkit.registerStage { new Stage() }
}
def cleanup() {
FxToolkit.hideStage()
// as explained for org.testfx.robot.KeyboardRobot, passing an
// empty array of the appropriate type releases all keys/mouse buttons
// NB this is how you create an empty typed array in Groovy
release(new KeyCode[0])
release(new MouseButton[0])
}
#Override
public void start(Stage stage) throws Exception {
Parent mainNode = FXMLLoader.load( App.class.getResource("sample.fxml"))
stage.scene = new Scene(mainNode)
stage.show()
stage.toFront()
}
def "test English input"(){
when:
Label label = lookup("#label").query()
clickOn("#inputField")
write("This is a test!")
clickOn("#applyButton")
then:
label.text == "This is a test!"
}
}
src/main/resources/core/sample.fxml // NB note inclusion of "core" (package name)
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<GridPane alignment="center" hgap="10" vgap="10"
xmlns:fx="http://javafx.com/fxml/1"
xmlns="http://javafx.com/javafx/8.0.111"
fx:controller="core.Controller">
<children>
<TextField layoutX="15.0" layoutY="25.0" fx:id="inputField" />
<Label layoutX="15.0" layoutY="84.0" text="TEXT GOES HERE"
fx:id="label" />
<Button layoutX="124.0" layoutY="160.0" mnemonicParsing="false"
text="Apply" onAction="#applyButtonClicked" fx:id="applyButton" />
</children>
</GridPane>

Why is inclusion of Kafka breaking my Spring controller's unit test?

I am creating a Spring Boot web application that will utilise Kafka. I have created a trivial controller that will return a string.
// src/main/groovy/RootController.groovy
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ResponseBody
/**
* Controller to serve the index page
*/
#Controller
class RootController {
/**
* Serves the index page
*
* #return A string to appear on the index page
*/
#GetMapping("/")
#ResponseBody
String loadPage() {
return "root/index"
}
}
I have a unit test for this that uses Spock.
// src/test/groovy/RootControllerTest.groovy
import org.springframework.test.context.web.WebAppConfiguration
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import spock.lang.Specification
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
#WebAppConfiguration
class RootControllerTest extends Specification {
MockMvc mockMvc
// Setup for tests happens here˚
void setup() {
mockMvc = MockMvcBuilders.standaloneSetup(new RootController()).build()
}
// Cleanup for tests happens here
void cleanup() {}
def "LoadPage should return the string root/index"() {
when: 'the loadPage endpoint is hit'
def response = mockMvc.perform(get("/"))
then: 'the method loadPage returns the string root/index'
response.andExpect(status().isOk())
.andExpect(content().string("root/index"))
}
}
When run, this test passes. I have the following build.gradle file that will build and run the tests.
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.1.RELEASE")
}
}
plugins {
id 'org.springframework.boot' version '1.5.1.RELEASE' // Spring Boot
}
group 'dummy'
version '1.0-SNAPSHOT'
task wrapper(type: Wrapper) {
gradleVersion = '3.1'
distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
}
apply plugin: 'groovy'
sourceCompatibility = 1.8
def kafkaVersion = '0.10.0.0'
repositories {
maven {
name "confluent"
url "http://packages.confluent.io/maven/"
}
mavenCentral()
}
dependencies {
compile "org.codehaus.groovy:groovy-all:2.4.4" // Groovy version
compile "org.springframework.boot:spring-boot-starter-thymeleaf" // For thymeleaf
//compile "org.apache.kafka:kafka_2.11:${kafkaVersion}-cp1" // Kafka, as produced by confluent, hence -cp1 suffix
// Testing dependencies go here
testCompile "org.springframework:spring-test:4.3.6.RELEASE"
testCompile "org.spockframework:spock-core:1.0-groovy-2.4" // Spock (Mandatory)
}
However, when I uncomment the Kafka dependency, the build fails like this:
$ gradle clean test
:clean
:compileJava UP-TO-DATE
:compileGroovy
:processResources UP-TO-DATE
:classes
:compileTestJava UP-TO-DATE
:compileTestGroovy
:processTestResources UP-TO-DATE
:testClasses
:test
RootControllerTest > LoadPage should return the string root/index FAILED
java.lang.ExceptionInInitializerError at RootControllerTest.groovy:21
Caused by: java.lang.IllegalStateException at RootControllerTest.groovy:21
1 test completed, 1 failed
:test FAILED
FAILURE: Build failed with an exception.
What is it that is causing the failure please?

Can't run a jar-file, built from groovy-code compiled with gradle

I'm trying to compile (with gradle) and execute (with the java 1.8 runtime) a small groovy program (see helloWorld.groovy, below).
But when I try to invoke it, I get Error: Could not find or load main class helloWorld
What am I missing?
compile:
lexu> gradle clean jar
:clean
:compileJava UP-TO-DATE
:compileGroovy UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar
BUILD SUCCESSFUL
Total time: 0.555 secs
execute:
lexu> java -jar ./build/libs/helloWorld.jar
Error: Could not find or load main class helloWorld
helloWorld.groovy:
class helloWorld {
static void main(String[] args) {
println('Hello World');
}
}
build.gradle:
apply plugin: 'groovy'
apply plugin: 'application'
mainClassName = "helloWorld"
archivesBaseName = 'helloWorld';
configurations {provided; inlib;}
repositories {mavenCentral()}
dependencies {compile 'org.codehaus.groovy:groovy-all:2.4.7'}
jar {
manifest {
attributes(
'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
'Main-Class': 'helloWorld'
)
}
}
There are a couple of issues with your setup.
Not breaking, but worth mentioning here: Convention states your filenames and classes should be uppercase: HelloWorld.groovy
gradle assumes your source files to be under src/main/java or in this case, src/main/groovy. You can configure it according to your preferences with gradle groovy plugin - project layout:
sourceSets {
main {
groovy {
srcDirs = ['src/groovy']
}
}
}
You need to include all runtime dependencies for groovy in your jar-archive. For this, let's use use an extended task called uberjar.
build.gradle:
apply plugin: 'groovy'
apply plugin: 'application'
mainClassName = "HelloWorld"
archivesBaseName = 'HelloWorld';
configurations {provided; inlib;}
repositories {mavenCentral()}
dependencies {compile 'org.codehaus.groovy:groovy-all:2.4.7'}
task uberjar(type: Jar,dependsOn:[':compileJava',':compileGroovy']) {
from files(sourceSets.main.output.classesDir)
from configurations.runtime.asFileTree.files.collect { zipTree(it) }
manifest {
attributes 'Main-Class': mainClassName
}
}
HelloWorld.groovy:
class HelloWorld {
static void main(String[] args) {
println('Hello World');
}
}

Unable to run a TestNG with Gradle

I have a simple code which runs with TestNG, but I am unable to run the same with Gradle, as it says no main method is found, which is, well, not surprising since I am using annotations.
But in such a scenario, how to run the code if I must use Gradle.
Kindly note, I am very new to Gradle, and do not harbour much knowledge about the same.
Code:
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class tryTestNG
{
#BeforeClass
public void setup()
{
System.out.println("I am in Setup");
}
#Test
public void test()
{
System.out.println("I am in Test");
}
#AfterClass
public void tearDown()
{
System.out.println("I am in tearDown");
}
}
The above code runs perfectly with TestNG Library. However not with Gradle.
Here is my Gradle Build setup:
apply plugin: 'java'
apply plugin: 'application'
mainClassName = 'tryTestNG'
sourceCompatibility = 1.7
targetCompatibility = 1.7
version = '1.0'
repositories {
mavenCentral()
}
test {
useTestNG()
}
dependencies {
compile group: 'org.testng', name: 'testng', version: '6.9.10'
}
The Gradle returns that there is no Main Method.
Working Directory: /home/avirup/MyWorkspace/JavaWorkspace/TestNGGradle
Gradle User Home: /home/avirup/.gradle
Gradle Distribution: Gradle wrapper from target build
Gradle Version: 2.9
Java Home: /usr/lib/jvm/java-8-oracle
JVM Arguments: None
Program Arguments: None
Gradle Tasks: run
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:runError: Main method not found in class tryTestNG, please define the main method as:
public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':run'.
> Process 'command '/usr/lib/jvm/java-8-oracle/bin/java'' finished with non-zero exit value 1
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 0.514 secs
Thanks for your help.
There's no need to use application plugin to run tests.
The build.gradle should be:
apply plugin: 'java'
sourceCompatibility = 1.7
targetCompatibility = 1.7
version = '1.0'
repositories {
mavenCentral()
}
test {
useTestNG()
}
dependencies {
compile group: 'org.testng', name: 'testng', version: '6.9.10'
}
And the command: gradle test. Also, put tryTestNG under src/test/java and name it with capital letter.
Here is a demo.
Also mind that println statements from tests won't be visible in console. To view them navigate to test report. It's under: <project_dir>/build/reports/tests/index.html.

Resources