Unresolved reference: sourceSets for Gradle Kotlin DSL - gradle

Trying to migrate my existing build.gradle to Kotlin and I am getting the following error in my project:
Script compilation error:
Line 86: from(sourceSets["main"].allSource)
^ Unresolved reference: sourceSets
1 error
The error is coming from my subprojects block when I try to define the sourcesJar task:
subprojects {
val sourcesJar by tasks.registering(Jar::class) {
classifier = "sources"
from(sourceSets["main"].allSource) // error here
}
configure<PublishingExtension> {
publications {
register("mavenJava", MavenPublication::class) {
from(components["java"])
artifact(sourcesJar.get())
}
}
}
val implementation by configurations
val compileOnly by configurations
val annotationProcessor by configurations
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlin:kotlin-reflect")
compileOnly("org.springframework.boot:spring-boot-autoconfigure")
// ...
}
}
I'm using the following:
Gradle 4.10.2
Kotlin 1.2.70
Beginning part of the build.gradle.kts before subprojects block:
import com.diffplug.gradle.spotless.KotlinExtension
import com.diffplug.gradle.spotless.SpotlessExtension
import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
val kotlinVersion: String by extra
val springBootVersion: String by extra
buildscript {
val kotlinVersion: String by extra { "1.2.70" }
val springBootVersion: String by extra { "2.0.6.RELEASE" }
repositories {
maven {
val nexusPublicRepoURL: String by project
url = uri(nexusPublicRepoURL)
}
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
classpath("com.diffplug.spotless:spotless-plugin-gradle:3.9.0")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
classpath("org.jetbrains.kotlin:kotlin-compiler-embeddable:1.2.70")
}
}
allprojects {
val projectGroup: String by project
group = projectGroup
apply(plugin = "kotlin")
apply(plugin = "java-library")
apply(plugin = "maven-publish")
apply(plugin = "kotlin-spring")
apply(plugin = "com.diffplug.gradle.spotless")
apply(plugin = "io.spring.dependency-management")
configure<DependencyManagementExtension> {
imports {
mavenBom("org.springframework.boot:spring-boot-dependencies:$springBootVersion")
mavenBom("org.springframework.cloud:spring-cloud-dependencies:Finchley.SR1")
}
}
repositories {
maven {
val nexusPublicRepoURL: String by project
url = uri(nexusPublicRepoURL)
}
}
tasks.existing(KotlinCompile::class) {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
}
configure<SpotlessExtension> {
kotlin {
ktlint()
}
}
configure<PublishingExtension> {
repositories {
maven {
val nexusReleaseRepoURL: String by project
val nexusSnapshotRepoURL: String by project
val nexusUsername: String by project
val nexusPassword: String by project
val version = if ((project.version as String).contains("SNAPSHOT")) nexusReleaseRepoURL else nexusSnapshotRepoURL
url = uri(version)
credentials {
username = nexusUsername
password = nexusPassword
}
}
}
}
}

Since the plugin is applied imperatively in the same build script, Gradle can't know the plugin is applied and thus can't generate the extension functions allowing to access the source sets.
So you need to get the source set programmatically:
project.the<SourceSetContainer>()["main"]
Don't use
the<SourceSetContainer>()["main"]
otherwise the the() function will be resolved on the current task being configured instead of the project.

Related

Deploy in railway not working with gradle.build.kt

I need to deploy a aplication in railway, but any time returno this error:
Caused by: java.lang.ClassNotFoundException: br.com.zezinho.helpdesk
Error: Could not find or load main class br.com.zezinho.helpdesk
My path is correct.
github: https://github.com/Luciannodev/helpdesk-back
plugins {
java
id("org.springframework.boot") version "2.7.8"
id("io.spring.dependency-management") version "1.1.0"
}
group = "br.com.zezinho"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11
val mainClassName = "HelpDeskApplication.java"
configurations {
compileOnly {
extendsFrom(configurations.annotationProcessor.get())
}
}
repositories {
mavenCentral()
maven { url = uri("https://repo.spring.io/milestone") }
maven { url = uri("https://repo.spring.io/snapshot") }
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("io.jsonwebtoken:jjwt-api:0.11.5")
implementation("io.jsonwebtoken:jjwt-impl:0.11.5")
implementation("io.jsonwebtoken:jjwt-jackson:0.11.5")
implementation("mysql:mysql-connector-java:8.0.28")
implementation("com.h2database:h2:1.4.200")
testImplementation("org.springframework.boot:spring-boot-starter-test")
annotationProcessor("org.projectlombok:lombok")
}
tasks.withType<Test> {
useJUnitPlatform()
}
tasks.jar {
manifest.attributes["Main-Class"] = "br.com.zezinho.helpdesk"
manifest.attributes["Class-Path"] = configurations
.runtimeClasspath
.get()
.joinToString(separator = " ") { file ->
"libs/${file.name}"
}
}

Spring Dependency Management plugin for Spring Shell and Gradle multi-module project

I have a multi-module Gradle project which is structured like so:
root
|
|_____main
|
|_____other
This is how the build.gradle.ktss files are structured:
Root:
import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.8.0" apply false
kotlin("plugin.spring") version "1.8.0" apply false
kotlin("plugin.lombok") version "1.8.0" apply false
id("org.springframework.boot") version "2.7.2" apply false
id("io.spring.dependency-management") version "1.0.12.RELEASE" apply false
}
subprojects {
apply {
plugin("org.jetbrains.kotlin.jvm")
plugin("org.jetbrains.kotlin.plugin.spring")
plugin("org.jetbrains.kotlin.plugin.lombok")
plugin("org.springframework.boot")
plugin("io.spring.dependency-management")
}
configurations {
configurations["compileOnly"].extendsFrom(configurations["annotationProcessor"])
all {
exclude(group = "org.springframework.boot", module = "spring-boot-starter-logging")
}
}
repositories {
mavenCentral()
}
val implementation by configurations
val testImplementation by configurations
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
implementation("org.springframework.boot:spring-boot-starter")
//other dependencies...
}
configure<DependencyManagementExtension> {
imports {
mavenBom("org.springframework.shell:spring-shell-dependencies:2.1.0")
}
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict", "-Xjvm-default=all")
jvmTarget = "17"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
}
Main:
import org.springframework.boot.gradle.tasks.bundling.BootJar
plugins {
`java-test-fixtures`
application
}
group = "my.group"
version = "0.2.0"
java.sourceCompatibility = JavaVersion.VERSION_17
application {
mainClass.set("my.group.MainKt")
}
tasks.withType<BootJar> {
manifest {
attributes["Main-Class"] = "org.springframework.boot.loader.PropertiesLauncher"
}
}
task<JavaExec>("runBootJar") {
val bootJar: BootJar by tasks
classpath = files(bootJar)
debug = true
}
springBoot {
buildInfo()
}
extra["springShellVersion"] = "2.1.0"
dependencies {
implementation("org.springframework.boot:spring-boot-loader")
api("org.springframework.boot:spring-boot-starter-web")
api("org.springframework.boot:spring-boot-starter-batch")
api("org.springframework.boot:spring-boot-starter-data-mongodb")
api("org.springframework.boot:spring-boot-starter-data-jpa")
api("org.springframework.boot:spring-boot-starter-integration")
api("org.springframework.boot:spring-boot-starter-thymeleaf")
api("org.springframework.boot:spring-boot-starter-log4j2")
api("org.springframework.integration:spring-integration-mongodb")
api("org.springframework.boot:spring-boot-starter-mail")
api("org.springframework.shell:spring-shell-starter")
//other dependencies...
}
Other:
plugins {
`java-library`
}
group = "my.group"
version = "0.2.0"
java.sourceCompatibility = JavaVersion.VERSION_17
dependencies {
compileOnly(project(":main"))
implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
//other dependencies...
}
As you can see, Main has a dependency towards org.springframework.shell:spring-shell-starter, which in turns makes this piece inside the Root build.gradle.kts mandatory:
configure<DependencyManagementExtension> {
imports {
mavenBom("org.springframework.shell:spring-shell-dependencies:2.1.0")
}
}
If I try to move this part inside the Main script, the following error pops up when I try to compile Other:
Execution failed for task ':other:compileKotlin'.
> Could not resolve all files for configuration ':other:compileClasspath'.
> Could not find org.springframework.shell:spring-shell-starter:.
Required by:
project :other> project :main
Also, if I run Gradle with the stacktrace enabled, there is also this error:
2: Task failed with an exception.
-----------
* What went wrong:
java.lang.StackOverflowError (no error message)
This made me think there could be some kind of cyclic dependency, but I couldn't find any.
I'd like to move the mavenBom part inside Main because Spring Shell is only used there, and not in every submodule, but in the end I cannot get it working.
What am I missing?

Spring boot - Cannot subclass final class

I'm writing a back end in spring boot. I'm not sure if I've updated a package or what but after a few months of dev, suddenly I got this error on some of my controllers:
Error creating bean with name 'authApi' defined in file ... Cannot subclass final class
I've googled it and found some explanations of why Spring Boot need classes to be open so I was ready to mark all my classes as open but then my auto-wired constructor parameters and properties initialised in place are all null.
Here is an example controller:
#RestController
#RequestMapping("/api")
open class AuthApi(
private val userManager: UserManager,
private val authenticationManager: AuthenticationManager,
private val jwtEncoder: JwtEncoder
){
val logger = LoggerFactory.getLogger(AuthApi::class.java)
}
Here are my Gradle files. The issue appeared after I've updated the two submodule's Gradle files to disable bootJar. I'm not sure how that could affect the situation but maybe I've cleared some kind of cache and "triggered" an issue I've caused earlyer
Main:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import com.github.gradle.node.yarn.task.YarnTask
buildscript{
repositories {
maven {
url = uri("https://plugins.gradle.org/m2/")
}
}
dependencies{
classpath("com.github.node-gradle:gradle-node-plugin:3.2.1")
}
}
plugins {
id("org.springframework.boot") version "2.7.8"
id("io.spring.dependency-management") version "1.1.0"
kotlin("jvm") version "1.6.10"
kotlin("plugin.spring") version "1.6.10"
kotlin("plugin.jpa") version "1.5.21"
id("com.github.node-gradle.node") version "3.2.1"
}
allprojects {
apply(plugin = "io.spring.dependency-management")
apply(plugin = "org.springframework.boot")
apply(plugin = "com.github.node-gradle.node")
apply(plugin = "java")
apply(plugin = "kotlin")
group = "com.test"
version = "0.9.0"
java.sourceCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
}
}
subprojects {
apply(plugin = "java")
apply(plugin = "kotlin")
apply(plugin="io.spring.dependency-management")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "17"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
dependencies {
implementation("com.google.cloud:spring-cloud-gcp-dependencies:3.4.3")
implementation("com.google.cloud.sql:mysql-socket-factory:1.9.0")
implementation("com.google.cloud:google-cloud-storage:2.17.2")
implementation("org.springframework.cloud:spring-cloud-gcp-starter-sql-mysql:1.2.8.RELEASE")
implementation("org.springframework.boot:spring-boot-starter-actuator:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-security:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-data-jdbc:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-data-rest:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-data-jpa:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-web:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-validation:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-batch:2.7.8")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.3")
implementation("org.springframework.boot:spring-boot-starter-validation:2.7.8")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
runtimeOnly("com.h2database:h2:2.1.214")
implementation("org.hibernate.validator:hibernate-validator:7.0.5.Final")
runtimeOnly("mysql:mysql-connector-java:8.0.30")
implementation("com.google.zxing:core:3.5.0")
implementation("com.google.zxing:javase:3.5.0")
implementation("org.apache.commons:commons-csv:1.9.0")
implementation(project(":authentication"))
implementation(project(":commerce"))
testImplementation("org.springframework.boot:spring-boot-starter-test:3.0.2")
testImplementation(kotlin("test"))
}
Module 1
import org.springframework.boot.gradle.tasks.bundling.BootJar
tasks.getByName<BootJar>("bootJar") {
enabled = false
}
tasks.getByName<Jar>("jar") {
enabled = true
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-rest:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-security:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-data-jpa:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-data-jdbc:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-web:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-mail:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf:2.7.8")
implementation("com.nimbusds:nimbus-jose-jwt:9.23")
implementation("com.google.api-client:google-api-client-java6:2.0.0")
}
Module 2
import org.springframework.boot.gradle.tasks.bundling.BootJar
tasks.getByName<BootJar>("bootJar") {
enabled = false
}
tasks.getByName<Jar>("jar") {
enabled = true
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-rest:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-web:2.7.8")
implementation("org.springframework.boot:spring-boot-starter-data-jpa:2.7.8")
implementation("com.stripe:stripe-java:21.2.0")
implementation("org.springframework.boot:spring-boot-starter-security:2.7.8")
}
Edit 2:
Looking at the debugger, I've found that the original object has all the properties, seems like when I use userManager for example in an endpoint, it is accessing the proxy's property or something instead of the original one.

Import of external class in Kotlin Gradle Script not found

In my build.gradle.kts, I want to write a function that uses an external class: StrSubstitutor from Apach Commons Text. However, the import is not found, although I can see the library when I run ./gradlew dependencies.
The build.gradle.kts file is as follows:
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.apache.commons.text.StringSubstitutor // Import not found
plugins {
val kotlinVersion = "1.3.61"
kotlin("jvm") version "$kotlinVersion"
kotlin("kapt") version "$kotlinVersion"
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
}
dependencies {
implementation("org.apache.commons:commons-text:1.8")
// SourceSets
sourceSets.main {
withConvention(KotlinSourceSet::class) {
kotlin.srcDirs("src/main/kotlin")
}
}
sourceSets.test {
withConvention(KotlinSourceSet::class) {
kotlin.srcDirs("src/main/kotlin")
}
}
}
tasks.withType<Test> {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}
systemProperty("spring.profiles.active", "test")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
}
}
// Function that uses the import
fun getProperty(properties: Properties, propertyKey: String): String {
// Use the import "StrSubstitutor"
return ""
}
Is this possible with Kotlin, and if so: how?
Yes, it is possible. The reason it does not work as written is because you put the dependency on the Apache Commons Text into implementation configuration of the project, not into the classpath of the build script itself. So, you basically need to introduce a buildscript block to your build.gradle.kts file. Below is an example1:
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.apache.commons.text.StringSubstitutor
// TL DR: Add this block to your build script to make the import above work
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.apache.commons:commons-text:1.8")
}
}
tasks.register("hello") {
doLast {
println(StringSubstitutor.replaceSystemProperties(
"You are running with Java \${java.version} on OS \${os.name}."))
}
}
plugins {
val kotlinVersion = "1.3.61"
kotlin("jvm") version "$kotlinVersion"
kotlin("kapt") version "$kotlinVersion"
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
}
dependencies {
// You probably do not need this for your project, so I commented it out
// implementation("org.apache.commons:commons-text:1.8")
// SourceSets
sourceSets.main {
withConvention(KotlinSourceSet::class) {
kotlin.srcDirs("src/main/kotlin")
}
}
sourceSets.test {
withConvention(KotlinSourceSet::class) {
kotlin.srcDirs("src/main/kotlin")
}
}
}
tasks.withType<Test> {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}
systemProperty("spring.profiles.active", "test")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
}
}
Run this script with ./gradlew -q hello to check whether it works or not.
1 New task hello exists there just to demonstrate that the import works, it is not needed in the final build script that you would use in your project.

`runBlocking` coroutine builder is not resolved in the project (Other builders are resolved)

As the title suggest, the coroutine builder runBlocking is missing in the coroutine liblary I just added in my build.gradle. Funny thing is every other thing appears to be available, GlobalScope, CoroutineScope.launch CoroutineScope.async all present. runBlocking isn't. What am I doing wrong?
here is my build.gradle
buildscript {
ext {
ktor_version = "1.1.1"
kotlin_version = "1.3.20-eap-52"
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-frontend-plugin:0.0.44"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
}
}
plugins {
id 'kotlin-multiplatform' version '1.3.20-eap-100'
}
repositories {
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
maven { url 'https://dl.bintray.com/kotlin/kotlin-js-wrappers' }
maven { url 'https://dl.bintray.com/kotlinx/kotlinx' }
maven { url "https://kotlin.bintray.com/kotlinx" }
jcenter()
mavenCentral()
}
group 'books'
version '0.0.0'
apply plugin: 'maven-publish'
apply plugin: "org.jetbrains.kotlin.frontend"
kotlin {
jvm() {
compilations.all {
tasks[compileKotlinTaskName].kotlinOptions {
jvmTarget = "1.8"
}
}
}
js() {
compilations.all {
tasks[compileKotlinTaskName].kotlinOptions {
def optDir = compileKotlinTaskName.contains("Test") ? "test/${project.name}.test.js" : "main/${project.name}.js"
kotlinOptions.metaInfo = true
kotlinOptions.outputFile = "$project.buildDir.path/js/$optDir"
kotlinOptions.sourceMap = true
kotlinOptions.moduleKind = 'commonjs'
kotlinOptions.main = "call"
}
}
}
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib-common')
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$ktor_version"
}
}
commonTest {
dependsOn commonMain
dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
}
}
jvmMain {
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$ktor_version"
implementation kotlin('stdlib-jdk8')
}
}
jvmTest {
dependsOn jvmMain
dependencies {
implementation kotlin('test')
implementation kotlin('test-junit')
}
}
jsMain {
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$ktor_version"
implementation kotlin('stdlib-js')
}
}
jsTest {
dependsOn jsMain
dependencies {
implementation kotlin('test-js')
}
}
}
}
task runJest(type: Exec) {
group = "verification"
commandLine "sh", "runJest.sh"
}
runJest.dependsOn(jsTest)
task testAll() {
group = "verification"
dependsOn(jvmTest, runJest)
}
kotlinFrontend {
npm {
devDependency("karma")
}
sourceMaps = true
webpackBundle {
bundleName = "main"
host = "0.0.0.0"
contentPath = file("$buildDir.path/resources/main")
}
}
With that gradle configuration, I have been able to write tests well (Learning TDD) with kotlin-multiplatform. And here is my sample below
import kotlin.test.*
import com.luge.books.*
import kotlinx.coroutines.*
class BookTest {
#BeforeTest
fun setup() {
val book = Book()
}
#Test
fun testingInstantiation() {
val book = Book()
assertEquals(book.year, 1990, "Books do match the year")
}
#Test
fun willFail() {
assertFalse(false)
}
#Test
fun testingCoroutines() {
val job = GlobalScope.launch {
delay(5000)
println("Doing stuff")
assertTrue(false)
}
}
}
If you look closely, the test testingCoroutines passes, but since I am launching from the GlobalScope, it just fires and forgets and the test returns without throwing any error. If I incoporate runBlocking, the IDE highlights it with red color (you know, as something it doesn't understant), end even the kotlin compiler shouts, unresolved reference runBlockin. Help please....
After struggling here and there, I finally knew that runBlocking is only available in kotlin/jvm. So, it is not in kotlin/js or kotlin/common.
Just for future references, if you want to run multiplatform tests, then use this work around

Resources