基于 Micronaut 的应用程序构建的 Gradle 因不兼容而导致来自 3rd-party Snakeyaml lib 的 NoSuchMethodError 中断。使用 OpenAPI 生成器插件

Chr*_*ian 5 gradle openapi-generator micronaut-openapi

自上周(首次发生于 2023 年 5 月 9 日)以来,我们基于 Micronaut 的应用程序的 Gradle 构建失败了

[...]

> Task :openApiGenerate FAILED
Error snake-parsing yaml content
java.lang.NoSuchMethodError: org.yaml.snakeyaml.constructor.SafeConstructor: method 'void <init>()' not found
        at io.swagger.v3.parser.util.DeserializationUtils$CustomSnakeYamlConstructor.<init>(DeserializationUtils.java:393)
        at io.swagger.v3.parser.util.DeserializationUtils.readYamlTree(DeserializationUtils.java:207)
        at io.swagger.v3.parser.util.DeserializationUtils.deserializeIntoTree(DeserializationUtils.java:143)
        at io.swagger.v3.parser.OpenAPIV3Parser.readContents(OpenAPIV3Parser.java:165)
        at io.swagger.v3.parser.OpenAPIV3Parser.readLocation(OpenAPIV3Parser.java:94)
        at io.swagger.parser.OpenAPIParser.readLocation(OpenAPIParser.java:16)
        at org.openapitools.codegen.config.CodegenConfigurator.toContext(CodegenConfigurator.java:589)
        at org.openapitools.codegen.config.CodegenConfigurator.toClientOptInput(CodegenConfigurator.java:647)
        at org.openapitools.generator.gradle.plugin.tasks.GenerateTask.doWork(GenerateTask.kt:825)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java
        [...]
Run Code Online (Sandbox Code Playgroud)

该项目利用了——除其他外——

在调查了一些可能的根本原因后,对我来说,这似乎是由于 3rd-party lib 的snakeyaml版本与该库的“交叉使用”之间的1.332.0兼容更改引起的:

米克罗特3.9.1

使用snakeyaml版本,在他的BOM2.0中声明:

$ ./gradlew dependencyInsight --dependency org.yaml:snakeyaml
[...]

> Task :dependencyInsight
org.yaml:snakeyaml:2.0 (by constraint)
  Variant compile:
    | Attribute Name                     | Provided | Requested         |
    |------------------------------------|----------|-------------------|
    | org.gradle.status                  | release  |                   |
    | org.gradle.category                | library  | library           |
    | org.gradle.libraryelements         | jar      | classes+resources |
    | org.gradle.usage                   | java-api | java-api          |
    | org.gradle.dependency.bundling     |          | external          |
    | org.gradle.jvm.environment         |          | standard-jvm      |
    | org.gradle.jvm.version             |          | 17                |
    | org.jetbrains.kotlin.platform.type |          | jvm               |

org.yaml:snakeyaml:2.0
+--- io.micronaut:micronaut-bom:3.9.1
|    \--- compileClasspath
[...]
Run Code Online (Sandbox Code Playgroud)

** 通过显式查询 BOM 的依赖关系来确认:

$ curl --silent https://repo1.maven.org/maven2/io/micronaut/micronaut-bom/3.9.1/micronaut-bom-3.9.1.pom | grep snakeyaml
 <snakeyaml.version>2.0</snakeyaml.version>
     <artifactId>snakeyaml</artifactId>
     <version>${snakeyaml.version}</version>
Run Code Online (Sandbox Code Playgroud)

6.6.0Gradle 的 OpenAPI 插件的当前版本

使用snakeyaml版本1.33;通过启动使用选项构建的 Gradle 发现了这一点--scan,此处显示了“Build (!!!) dependency”选项卡的摘录:

build.gradle
  com.google.cloud.tools.jib:com.google.cloud.tools.jib.gradle.plugin:3.+ => 3.3.2
  com.gorylenko.gradle-git-properties:com.gorylenko.gradle-git-properties.gradle.plugin:2.+ => 2.4.1
  io.micronaut.application:io.micronaut.application.gradle.plugin:3.+ => 3.7.9
  org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.8.21
  org.jetbrains.kotlin.kapt:org.jetbrains.kotlin.kapt.gradle.plugin:1.8.21
  org.jetbrains.kotlin.plugin.allopen:org.jetbrains.kotlin.plugin.allopen.gradle.plugin:1.8.21
  org.openapi.generator:org.openapi.generator.gradle.plugin:6.+ => 6.6.0
    org.openapitools:openapi-generator-gradle-plugin:6.6.0
      org.openapitools:openapi-generator:6.6.0
        com.fasterxml.jackson.core:jackson-databind:2.14.0 => 2.15.0
        com.fasterxml.jackson.datatype:jackson-datatype-guava:2.14.0 => 2.15.0
        com.fasterxml.jackson.datatype:jackson-datatype-joda:2.14.0 => 2.15.0
        com.github.ben-manes.caffeine:caffeine:2.9.3
        com.github.curious-odd-man:rgxgen:1.4
        com.github.jknack:handlebars-jackson2:4.2.1
        com.github.jknack:handlebars:4.2.1
        com.github.joschi.jackson:jackson-datatype-threetenbp:2.12.5
        com.github.mifmif:generex:1.0.2
        com.google.guava:guava:31.1-jre
        com.samskivert:jmustache:1.15
        commons-cli:commons-cli:1.5.0
        commons-io:commons-io:2.11.0
        io.swagger.parser.v3:swagger-parser:2.1.6
          commons-io:commons-io:2.11.0
          io.swagger.parser.v3:swagger-parser-v2-converter:2.1.6
          io.swagger.parser.v3:swagger-parser-v3:2.1.6
          org.yaml:snakeyaml:1.33 => 2.0  // <== HERE!!!
[...]
Run Code Online (Sandbox Code Playgroud)

据我所知,这里有两个选择:

  • 升级Gradle的OpenAPI插件以使用snakeyaml库版本2.0
  • 强制构建过程使用1.33此库的版本。

尝试了Gradle 文档中描述的一些方法,例如强制使用特定版本的瞬态库(此处为1.33Snakeyaml lib 的版本),但没有成功。

Micronaut 以及 OpenAPI Generator 插件的版本也略有“降级”,但没有成功。

非常感谢任何帮助、想法、提示。

谢谢。

问候

基督教

进一步调查/信息:

  • 强制使用snakeyaml:1.33insidebuild.gradle不能解决问题:

    buildscript {
      repositories {
        mavenCentral()
      }
      dependencies {
        classpath('org.yaml:snakeyaml:1.33')
      }
    }
    
    [...]
    
    configurations {
      micronautBoms {
        resolutionStrategy.force 'org.yaml:snakeyaml:1.33'
      }
    }
    
    [...]
    
    dependencies {
      [...]
      implementation('org.yaml:snakeyaml') {
        version {
          strictly '1.33'
        }
      }
      [...]
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 如上所述,OpenAPI Generator 插件使用了io.swagger.parser.v3:swagger-parser:2.1.6库,它本身声明使用snakeyaml库,但没有指定任何版本限制:

    $ curl --silent https://repo1.maven.org/maven2/io/swagger/parser/v3/swagger-parser-v3/2.1.14/swagger-parser-v3-2.1.14.pom | grep -A 1 -B 2 snakeyaml
         <dependency>
             <groupId>org.yaml</groupId>
             <artifactId>snakeyaml</artifactId>
         </dependency>
    
    Run Code Online (Sandbox Code Playgroud)

    也许在这里明确声明版本限制(例如1.*1.33)将使 Gradle 识别出该插件和 Micronaut(框架)的版本要求冲突。