Extending TestCompile and TestRuntime inside a plugin - gradle

With a "normal" JavaExec gradle task such as,
task('integrationTest',
type: JavaExec,
moreConf...) {
// Stuff
}
you can extends inherit compile- and runtime configurations like so,
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}
But, how do you do this with a task defined through Groovy? I.e.
def integrationTestTask = project.task(['type': JavaExec], 'integrationTest') {
stuff
}
I am writing a plugin to reduce some repeated code.

By adding the prerequisite sourceSets integrationTestCompile and ìntegrationTestRuntime` will be created and available to set,
project.task(['type': JavaExec], 'integrationTest') {
project.sourceSets {
integrationTest {
java {
// set stuff....
}
}
}
project.configurations {
// These two (integrationTestCompile/integrationTestRuntime) get created by the sourceSets block
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}
// stuff
}

Related

Protobuf gradle plugin: how to avoid module affects?

I have multimodule gradle project. When I add com.google.protobuf to build.gradle - it affects to testIntegration module.
Without plugin:
With plugin:
And the real problem is - when I run Jenkins build job - it freezes on testIntegration. Without plugin - all works fine.
gradle.build
apply plugin:'com.google.protobuf'
def grpcVersion = '1.30.0'
dependencies {
...
implementation "io.grpc:grpc-netty:${grpcVersion}"
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
implementation "io.grpc:grpc-stub:${grpcVersion}"
...
}
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.8.0"
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.30.0'
}
}
generateProtoTasks {
all()*.plugins {
grpc {}
}
}
}
main-gradle.build
...
subprojects {
configurations {
compileOnly {
extendsFrom annotationProcessor
}
testIntegrationImplementation.extendsFrom(testImplementation)
testIntegrationRuntimeOnly.extendsFrom(testRuntimeOnly)
}
sourceSets {
testIntegration {
compileClasspath += sourceSets.main.output
runtimeClasspath += sourceSets.main.output
}
}
...

Gradle 7: how to get list of implementation dependencies (including sub) in a task?

I need to have full list of dependencies necessary to run a project (so subdependencies are also important!).
task generateLibsDescriptor() {
doFirst {
configurations.compileClasspath.resolvedConfiguration.resolvedArtifacts.each {
println it
}
}
}
This code works, but there are also compileOnly dependencies listed. I tried to change compileClasspath to implementation, but had an error Resolving dependency configuration 'implementation' is not allowed as it is defined as 'canBeResolved=false'.
Is it possible to have a list of just implementation dependencies (with subdependencies)?
Configuration compileClasspath extends compileOnly and implementation. New config should be created which extends only implementation but resolvable.
configurations {
resolvableImpl.extendsFrom(implementation)
resolvableImpl.canBeResolved(true)
}
task generateLibsDescriptor() {
doFirst {
configurations.resolvableImpl.resolvedConfiguration.resolvedArtifacts.each {
println it
}
}
}

Gradle multiple project gradle build fail with lombok 1.8.10 but compile well

I'm developing a gradle-multiple-project java application, code works well with lombok in intellij (getter, setter method is visible), but when I run gradle build then fail, get the message:
~/EventStormingWorkShop/sources/coffeeshop/coffee-domain/src/main/java/solid/humank/port/adapter/OrderReceiverAdapter.java:41: error: cannot find symbol
String orderString= mapper.writeValueAsString(orderCreatedEvent.getDetail());
^
symbol: method getDetail()
location: variable orderCreatedEvent of type OrderCreatedEvent
Current environment:
Intellij : 2019.2.3
Gradle : 5.6.2
JDK : GraalVM 19.2.0 (compatible with JDK 1.8_0222)
lombok : 1.8.10
I had checked the lombok dependencies declaration in build.gradle.
compileOnly "org.projectlombok:lombok:${lombokVersion}"
annotationProcessor "org.projectlombok:lombok:${lombokVersion}"
testCompileOnly "org.projectlombok:lombok:${lombokVersion}"
testAnnotationProcessor "org.projectlombok:lombok:${lombokVersion}"
at compile time everything wen well.
Here is the build.gradle from my rootProject
buildscript {
ext {
quarkusJunitVersion = '0.22.0'
restAssuredVersion = '3.3.0'
cucumberVersion = '4.7.1'
lombokVersion = '1.18.10'
quarkusVersion = '0.23.1'
awsJavaVersion = '1.11.631'
awsVersion = '2.5.29'
}
}
apply from: file("${rootDir}/gradle/project.gradle")
List testCompilePackage = ["io.quarkus:quarkus-junit5:${quarkusJunitVersion}", "io.rest-assured:rest-assured:${restAssuredVersion}"]
List testImplementPackage = ["io.cucumber:cucumber-java8:${cucumberVersion}", "io.cucumber:cucumber-junit:${cucumberVersion}"]
List implementationPackage = ["io.quarkus:quarkus-resteasy",
"com.amazonaws:aws-java-sdk-lambda",
"com.amazonaws:aws-java-sdk-dynamodb",
"com.amazonaws:aws-lambda-java-core",
"com.amazonaws:aws-lambda-java-events",
"com.amazonaws:aws-java-sdk-events"]
subprojects { dir ->
repositories {
mavenCentral()
}
dependencies {
// Lombok Support
compileOnly "org.projectlombok:lombok:${lombokVersion}"
annotationProcessor "org.projectlombok:lombok:${lombokVersion}"
testCompileOnly "org.projectlombok:lombok:${lombokVersion}"
testAnnotationProcessor "org.projectlombok:lombok:${lombokVersion}"
// quarkus test
testCompile testCompilePackage
// cucumber test
testImplementation testImplementPackage
// quarkus
compile group: 'io.quarkus', name: 'quarkus-gradle-plugin', version: "${quarkusVersion}", ext: 'pom'
implementation enforcedPlatform("io.quarkus:quarkus-bom:${quarkusVersion}")
implementation platform("com.amazonaws:aws-java-sdk-bom:${awsJavaVersion}")
implementation platform("software.amazon.awssdk:bom:${awsVersion}")
implementation implementationPackage
}
if (dir.name.endsWith("-domain")) {
dependencies {
implementation project(":ddd-commons")
}
}
if (dir.name.endsWith("-application")) {
String modName = dir.name.substring(0, dir.name.lastIndexOf("-application"))
dependencies {
implementation project(":ddd-commons"), project(":${modName}-domain")
}
}
if (dir.name.endsWith("-web")) {
String modName = dir.name.substring(0, dir.name.lastIndexOf("-web"))
dependencies {
implementation project(":ddd-commons"), project(":${modName}-domain"), project(":${modName}-application")
}
}
}
The build.gradle will apply a project.gradle file
project.gradle:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'io.quarkus:quarkus-gradle-plugin:0.23.1'
}
}
defaultTasks 'clean', 'build'
apply plugin: 'idea'
subprojects {
apply plugin: 'java'
apply plugin: io.quarkus.gradle.QuarkusPlugin
group 'solid.humank.coffeeshop'
version '1.0'
sourceCompatibility = 1.8
targetCompatibility = 1.8
idea.module.inheritOutputDirs = true
dependencies{
compileOnly "org.projectlombok:lombok:1.18.10"
annotationProcessor "org.projectlombok:lombok:1.18.10"
testCompileOnly "org.projectlombok:lombok:1.18.10"
testAnnotationProcessor "org.projectlombok:lombok:1.18.10"
}
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
options.deprecation = true
options.compilerArgs += ['-Xlint:none', '-proc:none', '-nowarn']
}
repositories {
mavenCentral()
mavenLocal()
}
buildDir = "${rootDir}/build/${rootDir.relativePath(projectDir)}"
tasks.named('test') {
useJUnitPlatform()
failFast = true
testLogging.showStandardStreams = true
testLogging.exceptionFormat 'full'
}
tasks.named('jar') {
// put parent name in final jar name, to resolve collision of child projects with same name under different parents
if (parent.depth > 0) {
archiveBaseName = "${parent.name}-${archiveBaseName.get()}"
}
}
afterEvaluate {
def buildTime = new Date()
tasks.withType(Jar) {
String ClassPathString = ''
configurations.runtime.each { ClassPathString += " lib\\" + it.name }
manifest {
attributes 'Implementation-Title': project.name,
'Implementation-Version': project.version,
'Created-By': "${System.getProperty('java.version')} (${System.getProperty('java.vendor')})",
'Built-With': "gradle-${project.gradle.gradleVersion}, groovy-${GroovySystem.version}",
'Built-By': System.getProperty('user.name'),
'Built-On': "${InetAddress.localHost.hostName}/${InetAddress.localHost.hostAddress}",
'Build-Time': buildTime.format('yyyy/MM/dd HH:mm:ss'),
'Class-Path': ClassPathString
}
}
}
}
Besides, there is the settings.gradle to include sub projects
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == 'io.quarkus') {
useModule("io.quarkus:quarkus-gradle-plugin:0.23.1")
}
}
}
}
rootProject.name = 'coffeeshop'
include 'ddd-commons'
include 'inventory-domain'
include 'inventory-application'
include 'inventory-web'
include 'coffee-application'
include 'coffee-domain'
include 'coffee-web'
include 'orders-application'
include 'orders-domain'
include 'orders-web'
I expect these settings could run gradle build well, but faced seems lombok annotation processer not worked issue in gradle runtime.
Because your project.gradle has '-proc:none'

Kotlin Gradle Could not find or load main class

I tried to copy the Spring Boot Kotlin sample project https://github.com/JetBrains/kotlin-examples/tree/master/tutorials/spring-boot-restful. I Added some more dependencies and when I tried to build the executable jar and run it, I got the error:
Could not find or load main class...
Gradle build script:
buildscript {
ext.kotlin_version = '1.1.3' // Required for Kotlin integration
ext.spring_boot_version = '1.5.4.RELEASE'
repositories {
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // Required for Kotlin integration
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version" // See https://kotlinlang.org/docs/reference/compiler-plugins.html#kotlin-spring-compiler-plugin
classpath "org.springframework.boot:spring-boot-gradle-plugin:$spring_boot_version"
}
}
/*plugins {
id 'org.springframework.boot' version '2.0.0.RELEASE'
}*/
apply plugin: 'kotlin' // Required for Kotlin integration
apply plugin: "kotlin-spring" // See https://kotlinlang.org/docs/reference/compiler-plugins.html#kotlin-spring-compiler-plugin
apply plugin: 'org.springframework.boot'
jar {
baseName = 'gs-rest-service'
version = '0.1.0'
from {
(configurations.runtime).collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes 'Main-Class': 'org.jetbrains.kotlin.demo.Applicationkt'
}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin/'
test.java.srcDirs += 'src/test/kotlin/'
}
repositories {
jcenter()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" // Required for Kotlin integration
compile("org.springframework.boot:spring-boot-starter-web")
compile group: 'org.apache.camel', name: 'camel-quartz2', version: '2.20.2'
compile group: 'org.apache.camel', name: 'camel-http4', version: '2.20.2'
compile group: 'org.apache.camel', name: 'camel-docker', version: '2.20.2'
compile group: 'org.apache.camel', name: 'camel-aws', version: '2.20.2'
testCompile('org.springframework.boot:spring-boot-starter-test')
}
Change Applicationkt to ApplicationKt will work, and BTW you may upgrade Kotlin version to 1.3.50.
By Applicationkt I mean the one in this line:
attributes 'Main-Class': 'org.jetbrains.kotlin.demo.Applicationkt'
Kotlin compiles the Application file in two different files:
one file called Application.class with the Springboot things
another file called ApplicationKt.class with the main method
In this second file is where the main function is located at, so you have to use this name in the build.gradle file.
mainClassName = 'org.jetbrains.kotlin.demo.ApplicationKt'
Update your build.gradle to
jar {
manifest {
attributes 'Main-Class': 'org.jetbrains.kotlin.demo.ApplicationKt'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
with an upper case K in ApplicationKt.
This is required because of the way Kotlin compiles to Java Bytecode. The fun main() function in Kotlin is not attached to any class, but Java always requires a class and does not support classless functions.
The Kotlin compiler has to create a Java class. Because you already defined a class Application it created one with the suffix Kt for the functions in your Kotlin file org/jetbrains/kotlin/demo/Application.kt. You have to set this class so that the JVM can find it.
BTW a Jar file is just a Zip file, you can unpack it and see for yourself if the ApplicationKt.class is there.
For me the main function needed to be outside the class body
#SpringBootApplication
#Configuration
class Application
(private val locationRepository: LocationRepository,
) : CommandLineRunner {
override fun run(vararg args: String?) {
whatever()
}
}
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
Indeed, Kotlin create file ApplicationKt.class in the jar if your main class file is named Application.kt. You have to add the following lines:
apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName = 'org.jetbrains.kotlin.demo.ApplicationKt'
If you use the classic jar plugin, you can do as below (which is described in previous responses):
jar {
manifest {
attributes 'Main-Class': 'org.jetbrains.kotlin.demo.ApplicationKt'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
However, my preference is to use bootJar plugin which is much clear and which allow me to use layered jars for example:
bootJar {
layered() // Not useful if you don't want to use layered jars
}

integrationTestCompile gradle dependency ignored

Following a few blog posts I tried to create a separate source folder for integration testing in gradle. I wanted also to add some additinal (arquillian) dependencies to my integrationTest task, but the integrationTestCompile seems to be ignored and I get a compilation error with the additional dependecy not resolved. When I change the dependecy to testCompile it works fine. Why is that so and how to change it? My simple test class:
//compilation fails with [Static type checking] - The variable [ArquillianSputnik] is undeclared
#TypeChecked
#RunWith(ArquillianSputnik)
class TestSpec extends Specification {
}
and gradle.build:
apply plugin: 'groovy'
apply plugin: 'war'
war.dependsOn 'native2ascii'
task native2ascii << {
ant.delete() {
fileset(dir: "${processResources.destinationDir}") {
include(name: '*.properties')
}
}
ant.native2ascii(src: 'src/main/resources/',
dest: "${processResources.destinationDir}",
includes: '**/*.properties',
encoding: 'UTF-8')
}
repositories {
mavenCentral()
maven {
url 'http://repository.jboss.org/nexus/content/groups/public'
}
mavenLocal()
}
sourceSets.main.java.srcDirs = []
sourceSets.main.groovy.srcDirs += ["src/main/java"]
sourceSets {
integrationTest {
groovy.srcDir file('src/integration-test/groovy')
resources.srcDir file('src/integration-test/resources')
compileClasspath = sourceSets.main.output + configurations.testCompile
runtimeClasspath = output + compileClasspath + configurations.testRuntime
}
}
dependencies {
//(...) non-test dependencies cut out for clarity
testCompile 'org.spockframework:spock-core:0.7-groovy-2.0'
testCompile 'cglib:cglib-nodep:2.2.2'
testCompile 'org.objenesis:objenesis:1.2'
//when integrationTestCompile is changed to testCompile the compilation works and the test is executed
integrationTestCompile 'org.jboss.arquillian.spock:arquillian-spock-container:1.0.0.Beta3'
integrationTestCompile 'org.jboss.arquillian.graphene:graphene-webdriver:2.0.3.Final'
integrationTestCompile 'org.jboss.as:jboss-as-arquillian-container-managed:7.2.0.Final'
}
task integrationTest(type: Test, dependsOn: 'test') {
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
}
check.dependsOn 'integrationTest'
First, you want to add to the compile and runtime classpaths rather than replace them. This really just means using the += operator rather than the = one. Additionally, you really only want to add the other sourcesets output, we'll deal with configurations separately.
compileClasspath += sourcesets.main.output + sourcesets.test.output
runtimeClasspath += sourcesets.main.output + sourcesets.test.output
Next, we'll want to configure our integration test configurations. Usually, this just means making them extend the test and compile ones so that they contain all those dependencies as well.
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}

Resources