简体   繁体   English

如何将 OpenAPI 客户端添加为子项目?

[英]How to add OpenAPI client as a subproject?

I can successfully add a generated openapi client to my project via source sets .我可以通过 source sets 成功地将生成的 openapi 客户端添加到我的项目中 But then I have to copy dependencies into the main build-gradle , resolve conflicts -> I think it would be a better design to have the client as a subproject with its own build.gradle .但是然后我必须将依赖项复制到主build-gradle中,解决冲突->我认为将客户端作为具有自己的build.gradle的子项目会是一个更好的设计。

So I add include = 'build:openapi-java-client' to my settings.gradle and compile project(':build:openapi-java-client') to my dependencies.所以我将include = 'build:openapi-java-client'添加到我的settings.gradle并将compile project(':build:openapi-java-client')到我的依赖项中。 So that I have the following files:这样我就有了以下文件:
build.gradle : build.gradle

plugins {
    id 'java'
    id 'application'
    id "org.openapi.generator" version "4.3.1"
}

repositories {
    jcenter()
}

openApiGenerate {
    generatorName = "java"
    inputSpec = "$rootDir/specs/petstore.yaml".toString()
    outputDir = "$buildDir/openapi-java-client".toString()
    apiPackage = "org.openapi.example.api"
    invokerPackage = "org.openapi.example.invoker"
    modelPackage = "org.openapi.example.model"
    configOptions = [
        dateLibrary: "java8"
    ]
}

dependencies {
    implementation 'com.google.guava:guava:29.0-jre'
    testImplementation 'junit:junit:4.13'
    
    compile project(':build:openapi-java-client')
}

application {
    mainClassName = 'a.aa.App'
}

and settings.gradle :settings.gradle

rootProject.name = 'simple-java-app'
include = 'build:openapi-java-client'

I execute openApiGenerate in advance, after adding it as a subproject, I do Gradle -> Refresh Gradle Project and Refresh.我提前执行openApiGenerate ,将其添加为子项目后,我执行Gradle -> Refresh Gradle Project and Refresh。

Eclipse then shows me a problem: Eclipse 然后告诉我一个问题:

Could not run phased build action using Gradle distribution 'https://services.gradle.org/distributions/gradle-6.5.1-bin.zip'.
Settings file 'C:\...\simple-java-app\settings.gradle' line: 11
A problem occurred evaluating settings 'simple-java-app'.
Could not set unknown property 'include' for settings 'simple-java-app' of type org.gradle.initialization.DefaultSettings.

I don't know where to go from here, addressing subprojects in subfolders worked just fine when I worked through https://guides.gradle.org/creating-multi-project-builds/ and put greeting-library in a subfolder.greeting-library知道go从这里到哪里,当我在子文件夹中处理子项目时,处理子文件夹中的子项目工作得很好

You cannot configure it alike this, because build most certainly is an output directory, which would create a circular reference.你不能像这样配置它,因为build肯定是一个 output 目录,它会创建一个循环引用。 Better try to add a new module and add that generator plugin into that module.最好尝试添加一个新模块并将该生成器插件添加到该模块中。 If you can configure another module as outputDir , this could be referenced.如果您可以将另一个模块配置为outputDir ,则可以引用它。

Even if the plugin resides in the root project, the destination needs to be a module.即使插件驻留在根项目中,目标也必须是模块。

The point is, that the root project always executes, opposite to module configutions.关键是,根项目始终执行,与模块配置相反。

You are trying to make build/ a project when that directory specifically is not meant to be a project directory.当该目录不打算成为项目目录时,您正在尝试build/项目。 It's Gradle default build directory and likely 99% of other plugins and other Gradle plugins.它是 Gradle 默认构建目录和可能 99% 的其他插件和其他 Gradle 插件。

Simply change output directory to something else other than build/ :只需将output目录更改为build/以外的其他目录:

openApiGenerate {
    generatorName.set("java")
    inputSpec.set("$rootDir/specs/petstore.json")
    outputDir.set("$rootDir/openapi-java-client")
    apiPackage.set("org.openapi.example.api")
    invokerPackage.set("org.openapi.example.invoker")
    modelPackage.set("org.openapi.example.model")
}

Then include the project in your build with the correct syntax:然后使用正确的语法将项目包含在您的构建中:

// settings.gradle
include("openapi-java-client")

However, using the org.openapi.generator seems to generate an invalid build.gradle since I get the following error:但是,使用org.openapi.generator似乎会生成无效的build.gradle ,因为我收到以下错误:

FAILURE: Build failed with an exception.

* Where:
Build file 'C:\Users\fmate\code\example\openapi-java-client\build.gradle' line: 23

* What went wrong:
Could not compile build file 'C:\Users\fmate\code\example\openapi-java-client\build.gradle'.
> startup failed:
  build file 'C:\Users\fmate\code\example\openapi-java-client\build.gradle': 23: unexpected char: '\' @ line 23, column 35.
         main.java.srcDirs = ['src/main\java']

This obviously won't work how you wanted it to since it appears to be an issue with the Gradle plugin itself.这显然不会像您希望的那样工作,因为它似乎是 Gradle 插件本身的问题。 If you just need to include the generate code in your project, then just include the generated Java code as part of your main Java source:如果您只需要在项目中包含生成代码,那么只需将生成的 Java 代码包含在您的主要 Java 源代码中即可:

openApiGenerate {
    generatorName.set("java")
    inputSpec.set("$rootDir/specs/petstore.json")
    outputDir.set("$buildDir/openapi-java-client")
    apiPackage.set("org.openapi.example.api")
    invokerPackage.set("org.openapi.example.invoker")
    modelPackage.set("org.openapi.example.model")
}

tasks {
    compileJava {
        dependsOn(openApiGenerate)
    }
}

sourceSets {
    main {
        java {
            srcDir(files("${openApiGenerate.outputDir.get()}/src/main"))
        }
    }
}

But with this approach, you'll run into missing imports/dependencies.但是使用这种方法,您会遇到缺少导入/依赖项的情况。 It doesn't appear this plugin offers the ability to just generate the models/POJOs only, so updating the library property to native and including some missing dependencies manually, it all works:看起来这个插件并没有提供只生成模型/POJO的能力,所以library属性更新为本native并手动包含一些缺少的依赖项,这一切都有效:

plugins {
    java
    id("org.openapi.generator") version "5.0.0-beta"
}

repositories {
    mavenCentral()
}

group = "io.mateo.test"

dependencies {
    implementation(platform("com.fasterxml.jackson:jackson-bom:2.11.1"))
    implementation("com.fasterxml.jackson.core:jackson-databind")
    implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
    implementation("org.openapitools:jackson-databind-nullable:0.2.1")
    implementation("com.google.code.findbugs:jsr305:3.0.2")
    implementation("io.swagger:swagger-core:1.6.2")
}

openApiGenerate {
    generatorName.set("java")
    inputSpec.set("$rootDir/specs/petstore.json")
    outputDir.set("$buildDir/openapi-java-client")
    apiPackage.set("org.openapi.example.api")
    invokerPackage.set("org.openapi.example.invoker")
    modelPackage.set("org.openapi.example.model")
    library.set("native")
    configOptions.put("dateLibrary", "java8")
}

tasks {
    compileJava {
        dependsOn(openApiGenerate)
    }
}

sourceSets {
    main {
        java {
            srcDir(files("${openApiGenerate.outputDir.get()}/src/main"))
        }
    }
}

I've just answered a very similar question.我刚刚回答了一个非常相似的问题。 While my answer there is not perfect, I would personally still prefer the approach suggested there – and kind of repeated here:虽然我的答案并不完美,但我个人仍然更喜欢那里建议的方法 - 并且在这里重复:

Suggested Approach建议的方法

I would keep the builds of the modules that depend on the generated API completely separate from the build that generates the API.我会将依赖于生成的 API 的模块的构建与生成 API 的构建完全分开。 The only connection between such builds should be a dependency declaration.此类构建之间的唯一联系应该是依赖声明。 That means, you'll have to manually make sure to build the API generating project first and only build the dependent projects afterwards.这意味着,您必须手动确保首先构建 API 生成项目,然后才构建依赖项目。

By default, this would mean to also publish the API module before the dependent projects can be built.默认情况下,这意味着在构建依赖项目之前还要发布 API 模块。 An alternative to this default would beGradle composite builds – for example, to allow you to test a newly generated API locally first before publishing it.此默认设置的替代方案是Gradle 复合构建- 例如,允许您在发布之前先在本地测试新生成的 API。 However, before creating/running the composite build, you would have to manually run the API generating build each time that the OpenAPI document changes.但是,在创建/运行复合构建之前,您必须在每次 OpenAPI 文档更改时手动运行 API 生成构建。

Example例子

Let's say you have project A depending on the generated API.假设您有项目 A,具体取决于生成的 API。 Its Gradle build would contain something like this:它的 Gradle 构建将包含如下内容:

dependencies {
    implementation 'com.example:api:1.0'
}

Of course, the simple-java-app build described in the question would have to be adapted to produce a module with these coordinates:当然,问题中描述的simple-java-app构建必须适应生成具有这些坐标的模块:

openApiGenerate {
    // …
    groupId = "com.example"
    id = "api"
    version = "1.0"
}

Before running A's build, you'd first have to run在运行 A 的构建之前,您首先必须运行

  1. ./gradlew openApiGenerate from your simple-java-app project. ./gradlew openApiGenerate从您的simple-java-app项目。
  2. ./gradlew publish from the simple-java-app/build/openapi-java-client/ directory. ./gradlew publishsimple-java-app/build/openapi-java-client/目录发布。

Then A's build could fetch the published dependency from the publishing repository.然后 A 的构建可以从发布存储库中获取已发布的依赖项。

Alternatively, you could drop step 2 locally and run A's build with an additional Gradle CLI option:或者,您可以在本地删除第 2 步,并使用额外的 Gradle CLI 选项运行 A 的构建:

./gradlew --include-build $path_to/simple-java-app/build/openapi-java-client/ …

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM