5

我最近为一个 Spring Boot 项目将 Gradle 从 4.x 升级到了 6.6。我以为我终于把它全部启动并运行了,但后来意识到我们的一个应用程序可能会启动两个不同配置的类型任务BootRun(比如 A 和 B),但无法启动第二个 B 实例。

这是我尝试运行第二个实例时的错误:

Build file 'C:\Users\...\build.gradle' line: 17

Execution failed for task ':apps:myapp:bootRunB'.
> The value for task ':apps:myapp:bootRunB' property 'mainClass' is final and cannot be changed any further.

这是我build.gradle配置任务的文件的一部分:

task bootRunB(type: org.springframework.boot.gradle.tasks.run.BootRun, dependsOn: 'build') {
    group = 'Application'

    doFirst() {
        main = bootJar.mainClassName
        classpath = bootRun.classpath
        systemProperty '...'
    }
}

任何建议,将不胜感激。

4

4 回答 4

6

Gradle 最近引入了一个用于延迟配置的 API ,现在插件扩展和任务类型等内部功能已迁移到这个新 API。总之,可以说(几乎)构建脚本中的每个配置属性都应该使用Property<T>or Provider<T>(只读)而不是简单类型的 getter 和 setter 来实现T。为了提供向后兼容性,很多属性没有改变,但添加了新属性,旧属性读取和写入这些新属性。

这也是您的问题的情况,因为BootRunSpring Boot Gradle 插件中的JavaExec任务类型扩展了 Gradle 提供的任务类型。添加了新属性mainClass(a Property<string>),并main修改了旧属性以使用新属性。该方法从using中getMain()读取,而在使用 Groovy 中的语法时调用的 method写入using 。mainClassProperty.get()setMain(String)main = '...'mainClassProperty.set(String)

这一切都可以正常工作,但 Gradle 为他们的惰性配置 API 引入了一些额外的功能。这些特性之一是可写属性的最终确定(Property<>)。在构建的某个时间点,mainClass将读取任务属性(例如 )以用于其原始目的(运行任务),因此在该点之后的任何更改都不会生效。在早期版本的 Gradle 中,这会导致很多难以调试的问题,因为 Gradle 不会显示任何错误。现在,一旦这些属性被读取以用于其原始目的,它们就会被最终确定,当有人试图在之后更改它们时导致 Gradle 失败。

关于您的用例,属性mainClass(由 访问main)已经在doFirst闭包中完成,因此您需要提前应用此配置。由于您要将值设置为属性的值bootJar.mainClassName(这是一个简单的String),因此您必须确保在读取此属性以配置bootRunB任务之前具有其最终值:

bootJar {
    mainClassName = '...'
}

task bootRunB(type: org.springframework.boot.gradle.tasks.run.BootRun, dependsOn: 'build') {
    group = 'Application'

    main = bootJar.mainClassName
    // From this point, bootRun.classpath must not be changed !
    classpath = bootRun.classpath
    systemProperty '...'
}

为了消除对配置顺序的依赖,你可以创建一个Provider<String>using Project.provider(...)

task bootRunB(type: org.springframework.boot.gradle.tasks.run.BootRun, dependsOn: 'build') {
    group = 'Application'

    main = provider({ bootJar.mainClassName })
    classpath = bootRun.classpath
    systemProperty '...'
}
于 2020-09-14T20:31:02.150 回答
1

这是我们昨天修复它的方法:

task bootRunB(type: org.springframework.boot.gradle.tasks.run.BootRun, dependsOn: 'build') {
    group = 'Application'
    mainClass = 'com.App'

    doFirst() {
        main = bootJar.mainClassName
        classpath = bootRun.classpath
        systemProperty '...'
    }
}
于 2020-09-16T13:21:25.500 回答
0

bootRun 任务基于 JavaExec 任务。

它现在提供了一个接受提供者的新属性。代替填充 main 属性,填充 mainClass 属性:

使用 kts 脚本语言的示例:


tasks.register<BootRun>("myBootRunTask") {
    dependsOn("assemble")
    group = "Application"

    val bootJarTask = tasks.getByName<BootJar>("bootJar")

    mainClass.set(provider { bootJarTask.mainClassName })
    classpath = bootJarTask.classpath

   ...
}
于 2021-05-06T14:12:11.053 回答
0

当配置不正确时会出现此问题,因此您需要选择适当的短线命令。看下面的截图

看下面的截图

注意:在我的情况下,用户本地默认值:没有工作

于 2021-12-28T17:47:00.920 回答