Using the OpenAPI generator Gradle plugin
I'm not a fan of Gradle, but for enterprise projects sometimes you need to use them. There are many choices of installing the OpenAPI generator, why among all did I choose to use the Gradle plugin?
Well, the reason for me is when using the Gradle plugin, the configurations can be contained in a build.gradle
file, which is easy to be versioned. Think of Gradle as a powerful CLI, you can use it for other tasks that you'd normally need to write a script for that. The downside? The documentation can be a bit confusing (both OpenAPI and Gradle itself), I had to read multiple times and in multiple articles to understand what it does and how it works.
Another good thing? You can use Gradle for projects of any tech stack - in my case I usually use for Flutter projects. Hence in this article I would show the configurations I apply for my Flutter projects.
Pre-requisites:
Java JDK version 8 or higher
Install Gradle (no actually you don't need Gradle installed everywhere you need to run the script, but we do need Gradle to generate the Gradle wrapper, which is used to distribute Gradle binary that can run our OpenAPI plugin)
What you'd learn by the end of this guide:
Generate Gradle wrapper (a one-time task for each project)
Create
build.gradle
file in your projectRun the gradle task defined in
build.gradle
Generate Gradle Wrapper
This is easy. Run gradle wrapper
and a couple of files will be generated for you: gradlew
and gradlew.bat
. gradlew
will be used to execute gradle tasks in Unix systems, and gradlew.bat
on Windows machines. Generally you would want to check these into the source control system in your project.
Create build.gradle
If you don't have an existing build.gradle
at the root of your project (not the build.gradle
inside the android
folder nor the one inside the android/app
folder), create one. And then paste the following content:
plugins {
id "org.openapi.generator" version "7.3.0"
}
openApiGenerate {
// replace remoteInputSpec with inputSpec
// if the api.yaml file is not remotely hosted
remoteInputSpec.set(<url_to_api_yaml>)
// The name of the generator which will handle codegen.
generatorName = 'dart-dio'
// The output target directory into which code will be generated.
outputDir = "packages/backend_api"
// Sets specified global properties.
globalProperties = [
browserClient: 'false'
hideGenerationTimestamp: 'true'
]
// Defines whether or not model-related test files should be generated.
generateModelTests = false
// Defines whether or not api-related test files should be generated.
generateApiTests = false
// Defines whether or not model-related documentation files should be generated.
generateModelDocumentation = false
// Defines whether or not api-related documentation files should be generated.
generateApiDocumentation = false
// A map of options specific to a generator.
// see https://github.com/OpenAPITools/openapi-generator/blob/master/docs/generators/dart-dio.md#config-options
// for the full set of available options
configOptions = [
// Name in generated pubspec
pubName: 'backend_api'
]
// see https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator-gradle-plugin/README.adoc#openapigenerate
// for the full set of available options
}
Once this is saved, we can proceed to the final step - run it!
Run the OpenAPI generator
Now we are ready to execute it. Running ./gradlew openApiGenerate
(or ./gradlew.bat openApiGenerate
in Windows) will execute the OpenAPI generator task defined in the build.gradle
. If everything goes well you will see a generated package in the specified outputDir
.
Alternative way if you don't want to use Gradle
If you have read through the above steps and you still can't wrap your head over the trouble of maintaining a Gradle file, it is worth mentioning that you can download the .jar
binary directly and then execute in your terminal (you still need Java, of course):
#!/bin/bash
java -jar openapi-generator-cli.jar generate \
-i ./api.yaml \
-g dart-dio \
-o ./packages/backend_api \
--additional-properties hideGenerationTimestamp=true,browserClient=false \
# other properties ...
Some people prefer using this way, so I just leave the option open, feel free to choose whichever option that suits you and your team.