How to generate openAPI code using multiple yaml file
Asked Answered
T

5

17

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.

Thelen answered 26/9, 2019 at 14:6 Comment(0)
B
10

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
Bouse answered 23/4, 2020 at 22:9 Comment(3)
I used build.gradle.kts with this example, and my solution doesn't work. I will print my code in answer belowSissie
@defneo maybe you should adapt my Groovy code to Kotlin. What version are you using?Bouse
hi @defneo I'm using Gradle 5.6.4Bouse
T
5

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 
Thelen answered 18/11, 2019 at 15:59 Comment(0)
T
4

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"
Tab answered 21/6, 2021 at 4:31 Comment(0)
A
2

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"
}
Allurement answered 10/2, 2021 at 17:55 Comment(0)
P
2

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

    val openapiSpecs = mapOf(
        "api1" to "src/main/resources/openapi/api1.yml",
        "api2" to "src/main/resources/openapi/api2.yml"
    )
    openapiSpecs.forEach {
        tasks.create("openApiGenerate-${it.key}", org.openapitools.generator.gradle.plugin.tasks.GenerateTask::class) {
            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 "java8"
            ))
            sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).java.srcDir("$buildDir/generated/openapi/src")
        }
    }
    tasks.register("openApiGenerateAll") { dependsOn(openapiSpecs.keys.map { "openApiGenerate-$it" }) } 

Then gradle openApiGenerateAll will generate everything.

Precis answered 22/7, 2022 at 13:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.