无法使用 Liquibase 配置解析 Gradle 构建文件:表达式“main”无法作为函数调用

问题描述 投票:0回答:1

我对使用 Gradle 而不是 Maven 还比较陌生,但我认为它更适合 Kotlin 项目。

我正在使用 MySQL 数据库编写 Spring Boot 应用程序,并希望为其设置 Liquibase。该项目是使用 Spring Initializr 和 Liquibase 依赖项进行初始化的。我已经添加了(据我所知)必要的依赖项以及运行 Spring Boot 项目时运行 Liquibase 的插件。我还在网上找到的 Gradle 构建文件中配置了 Liquibase。 Liquibase 变更日志文件存在并且似乎有效;它只添加一个包含 2 列的表。

当我尝试构建(或使用 Gradle 包装器执行任何操作)时,Gradle 失败并显示

Expression 'main' cannot be invoked as a function. The function 'invoke()' is not found

在我的构建文件中包含“main”的配置行中。

以下是我的 gradle.build.kts 文件中看起来相关的摘录:

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

plugins {
    id("org.liquibase.gradle") version "2.2.1"
    kotlin("jvm") version "1.9.23"
}

java {
    sourceCompatibility = JavaVersion.VERSION_21
}

repositories {
    mavenCentral()
    maven { url = uri("https://repo.spring.io/milestone") }
}

dependencies {
    implementation("org.liquibase:liquibase-core")
    runtimeOnly("com.mysql:mysql-connector-j")
}

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


liquibase {
    activities {
        main {
            changeLogFile = "some/url/to/changelog/yaml/file"
            url = "jdbc:mysql://localhost:3306/someDatabase"
            username = "some-user"
            password = "some-password"
        }
    }
}

这是 Gradle 包装器的输出,没有路径和行号:

$ ./gradlew build

> Configure project :
e: Expression 'main' cannot be invoked as a function. The function 'invoke()' is not found
e: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public val NamedDomainObjectContainer<KotlinSourceSet>.main: NamedDomainObjectProvider<KotlinSourceSet> defined in org.gradle.kotlin.dsl
public val SourceSetContainer.main: NamedDomainObjectProvider<SourceSet> defined in org.gradle.kotlin.dsl
e: Unresolved reference: changeLogFile
e: Unresolved reference: url
e: Unresolved reference: username
e: Unresolved reference: password

当我运行 ./gradlew clean 时,它也会以同样的方式失败。 当我注释掉 liquibase { ... } 配置块时 ./gradlew build 运行良好并且 ./gradlew jobs 列出了 Liquibase 特定的任务。

有人可以解释为什么失败以及我能做些什么吗?

kotlin gradle liquibase gradle-kotlin-dsl
1个回答
0
投票

翻译问题

看起来您遇到了一些“翻译问题”:您编写了适合 Groovy DSL(另一种 Gradle 语言)而不是 Kotlin DSL 的代码。

当您在

activities {}
中编写代码时,您正在运行的代码将在
NamedDomainObjectContainer<Activity>
类型的对象范围内执行。这些类型的容器在 Gradle 中随处可见(请参阅 Kotlin DSL 指南中的讨论),而
TaskContainer
(通过构建脚本中的
tasks
访问)可能是最常见的。

时髦的行为

当您编写类似

main {}
的内容时,您正在调用一种“方法”,但该方法并未在您调用它的类中定义。在这种情况下,在
NamedDomainObjectContainer
的 Groovy Gradle 构建脚本中,这被视为名为
main
的域对象的配置,如果需要,会立即创建该对象。

Kotlin 方法

Kotlin 中没有这样的魔力1。作为静态类型语言,您需要调用范围内对象上存在的方法,或者是此类对象的扩展方法(可能是作为插件的结果自动创建的)。 Kotlin DSL 文档展示了原生可用的内容。

就您而言,您想做的是致电

register
2:

activities {
    register("main") {
        // do the configuration
    }
}

这实际上是对之前 Groovy 方法的改进,因为

register
会延迟配置
main
,并且在需要
main
之前不会运行配置代码。 (事实上,在最佳 Groovy 代码中,您最终会编写与 Kotlin 相同的代码,以便从这种惰性求值中受益。)


1 Kotlin DSL 有一种不同的魔力,有时插件中定义的对象会触发代码生成,因此您可以像 Groovy 示例一样编写代码。请参阅文档。但我不相信这里的情况是这样。

2 假设main

对象还没有被创建,在这种情况下你可以调用
named

© www.soinside.com 2019 - 2024. All rights reserved.