简体   繁体   中英

How to generate openAPI code using multiple yaml file

I have two yaml file, customer.yaml and employee.yaml. How do I generate java code from these two yaml file in single project. I'm using gradle, I know the task specification for single yaml but how do I specify multiple yaml. Should I specify mutiple inputSpec under single openApiGenerator? if yes then what is the exact syntax to do so. Below is my openApiGenerator task in build.gradle file.

``
openApiGenerate {
    generatorName = "spring"
    apiPackage = "com.xxx.generated.controller"
    modelPackage = "com.xxx.generated.model"
    inputSpec = "$rootDir//schema/employee.yaml".toString()
    outputDir = "$rootDir/generated".toString()
    configOptions = [
        dateLibrary: "java8"
    ]
    systemProperties = [
        invoker : "false", 
        generateSupportingFiles: "true"
    ]
    additionalProperties = [
        interfaceOnly : "true",
    ]
}
 ``

I heard of openApiGenerators task which Lists generators available via Open API Generators but couldn't find a way to use it.

Added following code in build.gradle and I was able to generate the java code. Copy the spec1 & spec2 yaml file under schema folder. Additionally, you need to have openApi plugin and dependencies configured in build.gradle.

task buildPaymentClient(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask){
generatorName = "spring"
inputSpec = "$rootDir//schema/spec1.yaml".toString()
outputDir = "$rootDir/generated".toString()
apiPackage = "com.abc.code.generated.controller"
modelPackage = "com.abc.code.generated.model"
configOptions = [
        dateLibrary: "java8"
]
systemProperties = [
    invoker : "false", 
    generateSupportingFiles: "true"
]
additionalProperties = [
    interfaceOnly : "true",
]

}

openApiGenerate {
    generatorName = "spring"
    apiPackage = "com.abc.code.generated.controller"
    modelPackage = "com.abc.code.generated.model"
    inputSpec = "$rootDir//schema/spec2.yaml".toString()
    outputDir = "$rootDir/generated".toString()
    configOptions = [
        dateLibrary: "java8"
    ]
    systemProperties = [
        invoker : "false", 
        generateSupportingFiles: "true"
    ]
    additionalProperties = [
        interfaceOnly : "true",
    ]
}

compileJava.dependsOn buildPaymentClient, tasks.openApiGenerate 

I succeeded in creating dynamically the tasks for each of the yaml files you have in your project. I'm using gradle 4.8.1 but I think that applies to next versions too.

import groovy.io.FileType
import org.openapitools.generator.gradle.plugin.tasks.GenerateTask

plugins {
    id "org.openapi.generator" version "4.1.3"
}

//here we are going to store swagger files
def swaggerList = []

//iteration by swagger file root folder and save into swaggerList variable
def dir = new File("$rootDir/src/main/resources/api/".toString())
dir.eachFileRecurse(FileType.FILES) { file ->
    if (file.getName().endsWith(".yaml"))
        swaggerList << file
}

// Iterate on all swagger files and generate a task for each one with the nomenclature openApiGenerate + swagger name
swaggerList.each {
    println it.path
    def apiName = it.getName().replace(".yaml", "");

    tasks.create("openApiGenerate" + apiName.capitalize(), GenerateTask.class, {
        generatorName = "jaxrs-spec"
        inputSpec = "$rootDir/src/main/resources/api/".toString() + "${apiName}.yaml"
        outputDir = "$buildDir/generated/openapi".toString()
        apiPackage = "my.package.rest.api.definition.".toString() + "${apiName}"
        modelPackage = "my.package.rest.api.model.".toString() + "${apiName}"
        templateDir = "$rootDir/src/main/resources/api/templates".toString()
        //    https://github.com/OpenAPITools/openapi-generator/blob/master/docs/generators/jaxrs-spec.md
        configOptions = [
                dateLibrary: "java8",
                java8: true,
                useBeanValidation: true,
                interfaceOnly: true,
                useOptional: true,
                useLombok: true
        ]
    })
}

sourceSets {
    main {
        java {
            srcDir("$buildDir/generated/openapi/src/gen/java")
            srcDir("$buildDir/generated/openapi/src/main/java")
        }
    }
}

After this if I have a swagger file named login.yaml and other named user.yaml user.yaml I call next gradle tasks:

gradle openApiGenerateLogin

Or

gradle openApiGenerateUser

Same problem here, different solution. I really like the idea of working in separate files, however, while sharing the spec within dev team or importing it in tools like postman, insomnia or some API gateway, a single file is really more accurate and simple.

So, I would like to recommend the use of openapi-merger-plugin for this task. It works like a charm.

Here is how I solved this problem:

// Merging all OpenAPI Files
openApiMerger {
    inputDirectory.set(file("${rootDir}/src/main/resources/api/".toString()))
    output {
        directory.set(file("${buildDir}/generated/openapi/".toString()))
        fileName.set("openapi")
        fileExtension.set("yaml")
    }
    openApi {
        openApiVersion.set("3.0.1")
        info {
            title.set("Open API Merger")
            description.set("All files merged by open api merger")
            version.set("${project.version}".toString())
            termsOfService.set("http://openapimerger.com/terms-of-service")
            contact {
                name.set("OpenApiMerger Team")
                email.set("openapi@sample.com")
                url.set("http://openapimerger.com")
            }
            license {
                name.set("Apache License v2.0")
                url.set("http://apache.org/v2")
            }
        }
        externalDocs {
            description.set("External docs description")
            url.set("http://external-docs.com/uri")
        }
    }
}

// Generating code only once
openApiGenerate {
    generatorName   = "spring"
    inputSpec       = "${buildDir}/generated/openapi/openapi.yaml"
    outputDir       = "${buildDir}/generated/openapi"
    packageName     = "com.xxx.generated"
    apiPackage      = "com.xxx.generated.controller"
    modelPackage    = "com.xxx.generated.model"
    modelNameSuffix = ""
    validateSpec    = true
    configOptions   = [
        dateLibrary         : "java8",
        interfaceOnly       : "true",
        swaggerDocketConfig : "false"
    ]
}

// Making generated source visible (classpath)
sourceSets {
    main {
        java {
            srcDir "${buildDir}/generated/openapi/src/main/java"
        }
    }
}

// Integrating plugin tasks with compiling
tasks.openApiGenerate {
    dependsOn  tasks.mergeOpenApiFiles
}
compileJava {
    dependsOn  tasks.openApiGenerate
    source "${buildDir}/generated/openapi/src/main/java"
}

In my cases I use same task options and ony with different spec yml file name, so here's my solution:

Assume you have 2 swagger yml files:

  • src/main/resources/swagger/api1.yml
  • src/main/resources/swagger/api2.yml

Then:

swagger.gradle :

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.openapitools:openapi-generator-gradle-plugin:${openapiPluginDependencyVersion}"
    }
}
apply plugin: "org.openapi.generator"

void createOpenApiGenerateTask(String ymlName) {
    String taskName = "openApiGenerate_" + ymlName;
    task(taskName, type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
        inputSpec = "$rootDir/src/main/resources/swagger/${ymlName}.yml".toString()
        // other common task options goes here...
        // e.g.
        // outputDir = "$buildDir/openapi".toString()
        // apiPackage = "com.example.api"
        // ...
    }
    compileJava.dependsOn(taskName)

}

String[] ymlNames = [
        "api1",
        "api2"
]
for (String ymlName : ymlNames) {
    createOpenApiGenerateTask(ymlName);
}

sourceSets {
    main {
        java {
            srcDir file("${project.buildDir.path}/openapi/src/main/java")
        }
    }
}

gradle.properties :

openapiPluginDependencyVersion=4.3.0

build.gradle :

apply from: "gradle/swagger.gradle"

The following worked for me adding it to the build.gradle.kts:

    mapOf(
        // the keys need to be sorded descendingly
        "api2" to "src/main/resources/openapi/api2.yml",
        "api1" to "src/main/resources/openapi/api1.yml"
    ).forEach {
        openApiGenerate {
            generatorName.set("kotlin")
            inputSpec.set("$rootDir/${it.value}")
            outputDir.set("$buildDir/generated/openapi")
            apiPackage.set("my.company.service.openapi")
            modelPackage.set("my.company.domain.openapi.${it.key}")

            configOptions.set(mapOf(
                "dateLibrary" to "java11"
            ))
            sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).java.srcDir("$buildDir/generated/openapi/src")
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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