原始 Axon 应用程序 运行,因为 Fat JAR 不会自动配置 Axon Bean

Primitive Axon App run as Fat JAR Doesn't Autoconfigure Axon Beans

问题:

研究:在 https://gitlab.com/ZonZonZon/simple-axon.git,我制作了一个简单的 Axon-app 来展示 JAR-artifact使用 Gradle-plugin com.github.johnrengelman.shadow 时(当 运行 为 JAR 时)不会自动配置 Axon bean。虽然它 运行 在 Intellij 下没问题。

从终端中的项目根目录:

run gradle clean build shadowJar;
java -jar build/simpleaxon.jar;

Stacktrace 已包含在内here。我希望 Axon Autoconfiguration 默认提供像 CommandBus、Snapshotter 和其他 bean。

问题:如何在 fat jar 中自动配置默认的 axon bean?

所以,这需要我进行一些调查才能预感到出了什么问题,但我知道问题出在哪里。 快速注意,这不是 Axon 特定的东西,而是您正在使用的插件。

我 运行 你的示例项目确实得到了相同的结果;从来没有连接过 Axon bean。这促使我逐步研究创建胖 JAR 的过程。首先是 Maven,然后 Spring 使用 Maven 引导,然后 Gradle 使用 Spring 引导,最后使用您所指的 Shadow 插件。

我的努力让我陷入了 this 问题,该问题与 "projects which require the use of META-INF files need to add this to the shadow plugin, and this should be documented" 一样多。

通过 this 引用的部分如下:

import com.github.jengelman.gradle.plugins.shadow.transformers.PropertiesFileTransformer

// Left out all other specifics from your 'build.gradle' file

shadowJar {
    // Required for Spring
    mergeServiceFiles()
    append 'META-INF/spring.handlers'
    append 'META-INF/spring.schemas'
    append 'META-INF/spring.tooling'
    transform(PropertiesFileTransformer) {
        paths = ['META-INF/spring.factories' ]
        mergeStrategy = "append"
    }

    setArchiveFileName("simpleaxon.jar")
    getDestinationDirectory().set(new File(projectDir, "./build"))
}

将那段逻辑添加到您的 build.gradle 文件后,我可以运行 您的示例项目如预期的那样。

我在多模块 Gradle 项目中使用 Axon 时遇到了类似的问题。该应用程序在 IDE 中打包并运行良好时无法运行。我得到的确切错误是

org.axonframework.messaging.annotation.UnsupportedHandlerException: Unable to resolve parameter 0 in handler

这是因为 ParameterResolverFactories 未加载,因为 META-INF/services 资源未在 shadow jar 插件中正确解析,正如@Steven 所暗示的。

我已经设法简单地修复了它(在 Gradle 中使用 Kotlin DSL):

tasks.shadowJar {
  mergeServiceFiles()
}

@Steven 的解决方案是唯一对我有用的解决方案,在搜索了很长时间的其他解决方案之后。

Gradle Kotlin 版本看起来像这样 https://github.com/spring-projects/spring-boot/issues/1828#issuecomment-607352468:

import com.github.jengelman.gradle.plugins.shadow.transformers.PropertiesFileTransformer
plugins {
    id("com.github.johnrengelman.shadow") version "7.1.2"
}
...
tasks.shadowJar {
    // Required for Spring.
    // The shadowJar plugin should merge the services correctly, but it doesn't!
    mergeServiceFiles()
    append("META-INF/spring.handlers")
    append("META-INF/spring.schemas")
    append("META-INF/spring.tooling")
    transform(
        PropertiesFileTransformer().apply {
            paths = mutableListOf("META-INF/spring.factories")
            mergeStrategy = "append"
        })
}