Смешайте Java и Kotlin в Gradle Kotlin DSL с помощью sourceSet

У меня есть проект, сочетающий Java и Kotlin.

Код Java в src/main/java вызывает код Kotlin в src/main/kotlin. Приложение запускается из Kotlin-части.

Смешайте Java и Kotlin в Gradle Kotlin DSL с помощью sourceSet

В build.gradle.kts полный контент

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    java
    id("project-report")
    id("org.springframework.boot") version "3.2.4"
    id("io.spring.dependency-management") version "1.1.4"
    kotlin("jvm") version "1.9.23"
    kotlin("plugin.spring") version "1.9.23"
}

group = "com.aaaaa"
version = "x.y.z-SNAPSHOT"


sourceSets {

    // https://stackoverflow.com/questions/38131237/mixing-java-and-kotlin-in-gradle-project-kotlin-cannot-find-java-class
    main {
        java.srcDirs("src/main/java","src/main/kotlin") 
        kotlin.srcDir("src/main/java")
    }
}


java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}


repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.jsoup:jsoup:1.17.2")
    implementation("io.github.jbock-java:either:1.5.2")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.htmlunit:htmlunit:4.2.0")

    developmentOnly("org.springframework.boot:spring-boot-devtools")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation ("org.junit.jupiter:junit-jupiter-api:5.8.1")
//  testRuntimeOnly ("org.junit.jupiter:junit-jupiter-engine:5.8.1")
}


tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs += "-Xjsr305=strict"
        jvmTarget = "17"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

Код Java не может найти код Kotlin, и во время сборки я получаю эту ошибку ./gradlew build:

Не удалось выполнить задачу «:compileJava».
Компиляция не удалась;

Странно, но в Gradle все работало без явного sourceSets до того, как я обновился до IntelliJ 2024.

Что не так в конфигурации sourceSets, чтобы код Java мог найти код Kotlin? Приложение запускается из Kotlin-части.

Я читал Создание проекта Kotlin + Java 9 с помощью Gradle

Решение состоит в том, чтобы установить каталог компиляции Kotlin в тот же каталог, что и Java:

compileKotlin.destinationDir = compileJava.destinationDir

Эта строка недействительна в Gradle 8.7 Kotlin DSL.

Рэнт: Серьезно, почему команда Gradle продолжает менять API на одном и том же языке DSL.

java.srcDirs("src/main/java","src/main/kotlin") kotlin.srcDir("src/main/java") - как по мне, это выглядит странно: javac не может скомпилировать котлин, более того, это отличается от принятого ответа по теме SO, о которой вы говорите.
Andrey B. Panfilov 14.06.2024 17:34

Я отредактировал пост, как вы предложили. Ошибка «:compileJava» присутствует.

Raymond Chenon 15.06.2024 18:42
kotlin.srcDir("src/main/java") это просто неправильно.
Martin Zeitler 15.06.2024 23:32
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
3
114
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Это намного проще, чем вы думаете: Java и Kotlin работают вместе «из коробки». Давайте немного успокоим команду Kotlin1:

Kotlin разработан с учетом совместимости Java. Существующий код Java можно вызывать из Kotlin естественным образом, а код Kotlin также можно довольно плавно использовать из Java.

А еще2:

Добавить классы Java в проект Kotlin довольно просто. Все, что вам нужно сделать, это создать новый файл Java.

Большая часть того, что вы делаете, — это настройка плагина Java. Однако плагин Kotlin JVM основан на плагине Java, и в большинстве случаев вам не нужно трогать плагин Java. Вместо этого вы нарушаете конфигурацию, которую плагин Kotlin JVM автоматически выполняет за вас.

Это означает, что все эти строки следует удалить:

sourceSets {
    main {
        java.srcDirs("src/main/java","src/main/kotlin") 
        kotlin.srcDir("src/main/java")
    }
}

И их можно удалить:

// within plugins {} block
    java

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

1https://kotlinlang.org/docs/java-interop.html

2https://kotlinlang.org/docs/mixing-java-kotlin-intellij.html#adding-java-source-code-to-an-existing-kotlin-project

Спасибо за явный sourceSets и ссылку на документацию. Это была еще одна проблема из-за модуля-info.java.

Raymond Chenon 15.06.2024 23:22
Ответ принят как подходящий

Я смотрел не туда.

У меня были файлы модулей. я удалил их

src/main/java/module-info.java
src/test/java/module-info.java

По сути src/main/java/module-info.java требуют импорта каждой библиотеки. Однако я не смог найти способ импортировать src/main/kotlin.

Удалив модули, все исправилось.

Спасибо всем за ответы и комментарии, у моего build.gradle.kts были эти конфигурации неявно. Установив sourceSets, теперь сборка явно нацелена на эти каталоги.

Любой, кто сталкивается с проблемой смешивания Java и Kotlin в одном проекте. Проверьте, есть ли у вас версия module-info.java.

Другие вопросы по теме