How to generate openAPI code using multiple yaml file

10,566

Solution 1

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

Solution 2

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 

Solution 3

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"

Solution 4

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("[email protected]")
                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"
}
Share:
10,566

Related videos on Youtube

Nicolas
Author by

Nicolas

Updated on June 04, 2022

Comments

  • Nicolas
    Nicolas almost 2 years

    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.

  • rgaponov
    rgaponov over 2 years
    I used build.gradle.kts with this example, and my solution doesn't work. I will print my code in answer below
  • atrujillofalcon
    atrujillofalcon over 2 years
    @defneo maybe you should adapt my Groovy code to Kotlin. What version are you using?
  • atrujillofalcon
    atrujillofalcon over 2 years
    hi @defneo I'm using Gradle 5.6.4