How to generate openAPI code using multiple yaml file
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"
}
Related videos on Youtube
Nicolas
Updated on June 04, 2022Comments
-
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 over 2 yearsI used build.gradle.kts with this example, and my solution doesn't work. I will print my code in answer below
-
atrujillofalcon over 2 years@defneo maybe you should adapt my Groovy code to Kotlin. What version are you using?
-
atrujillofalcon over 2 yearshi @defneo I'm using Gradle 5.6.4