Generate openapi‐generator flow and structure - ronreynolds/openapi-generator GitHub Wiki
NOTE - this is based on the code as of 2025-02-11 (7.12.0)
there appear to be two main classes (and two plugins, one for maven and one for gradle) in the openapi-codegen project:
-
org.openapitools.codegen.OpenAPIGenerator#main
- used for the openapi-generator-cli execution
- creates and populates a
io.airlift.airline.Cli.CliBuilder<OpenApiGeneratorCommand>
with a series of command classes - it then invokes
build().parse(args).run()
on the builder which triggers a whole series of events- checks for
--version
or--help
cmd-line args and processes them with immediate return - invokes one of these commands based on the command-line args passed in and
@Command
class annotation on each class:-
HelpCommand
- --help = Display help information about openapi-generator -
Version
---version
= Show version information used in tooling -
ConfigHelp
---config-help
= Config help for chosen language -
ListGenerators
---list
= Lists the available generators -
Meta
---meta
= Generator for creating a new template set and configuration for Codegen -
Validate
---validate
= Validate specification -
CompletionCommand
---completion
= Complete commands (for using in tooling such as Bash Completions) -
GenerateBatch
---batch
= Generate code in batch via external configs -
Generate
---generate
= Generate code with the specified generator- obviously this is the most interesting one
- performs various start-up tasks (dealing with specs, logging to stderr, config files, skip-validation, logging verbosity, etc)
- creates
CodegenConfigurator
and populates with various settings (including the spec, generator-name, etc) -
final ClientOptInput clientOptInput = configurator.toClientOptInput()
-
CodegenConfig config = CodegenConfigLoader.forName(generatorSettings.getGeneratorName())
- this is where the code-generator (which implements
CodegenConfig
) is actually created -
CodegenConfigLoader
is a pseudo-Classloader that will hunt for classes via ajava.util.ServiceLoader
to discover implementations ofCodegenConfig
with the name returned bygeneratorSettings.getGeneratorName()
- the file
modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
contains a complete list of*Codegen
classes and every one of them implementsorg.openapitools.codegen.CodegenConfig#getName
to return their specific language (e.g., "java") which, i suspect, is how the generator-name provided is mapped to the generator implementation class
- this is where the code-generator (which implements
-
-
new DefaultGenerator(isDryRun).opts(configurator.toClientOptInput()).generate();
(more or less)- at this point it's similar to the plugins (and probably the spring-boot server; didn't delve into that one too far)
-
- checks for
-
org.openapitools.codegen.online.OpenAPI2SpringBoot#main
- used for the openapi-generator-online service
- maven plugin (
org.openapitools.codegen.plugin.CodeGenMojo
) maps settings into aClientOptInput
and then creates and invokes aorg.openapitools.codegen.DefaultGenerator
- gradle plugin (
org.openapitools.generator.gradle.plugin.OpenApiGeneratorPlugin
) appears (it's written in Kotlin which i barely read) to do much the same based onorg.openapitools.generator.gradle.plugin.tasks.GenerateTask#doWork
- internalizes
ClientOptInput
and extracts various settings such as theio.swagger.v3.oas.models.OpenAPI
andCodegenConfig
- note, the
config
is actually the language-specific code-generator (e.g.,
- note, the
- preps the template engine, which may or may not be a Mustache engine; the alternative is "Handlebars" apparently
- also preps ignored files
- verifies that
openAPI
andconfig
are set and that the generator has metadata (tho missing metadata is only logged warning) -
configureGeneratorProperties()
- populate more instance variables from
GlobalSettings
-
GlobalSettings
is actually aInheritableThreadLocal<Properties>
populated initially fromSystem.getProperties
-
- process many configuration flags and performs many prep steps
- TODO - fill in with more detail
- populate more instance variables from
-
configureOpenAPIInfo()
- sets various versions, contact info, license info, etc.
-
config.processOpenAPI(openAPI)
-
config
is the
-
processUserDefinedTemplates()
generateOpenapiGeneratorIgnoreFile()
generateModels(files, allModels, filteredSchemas, aliasModels)
generateApis(files, allOperations, allModels)
generateWebhooks(files, allWebhooks, allModels)
bundle = buildSupportFileBundle(allOperations, allModels, aliasModels, allWebhooks)
generateSupportingFiles(files, bundle)
- if
dryRun
then just dump info to console (as error?) - if
!dryRun
andgenerateSupportingFiles
generateFilesMetadata(files)
config.postProcess()
- GlobalSettings.reset()`
my current use of the openapi-generator is via gradle-plugin configured thus:
openApiGenerate {
inputSpec.set("$rootDir/src/main/resources/smartsheet-v2-openapi-v3.0.3.json")
outputDir.set("$rootDir/build/generated/api")
templateDir.set("$rootDir/src/main/resources/templates") // where the custom mustaches live...
// packages to generate
invokerPackage.set("$group.smartsheet")
apiPackage.set("$group.smartsheet.api")
modelPackage.set("$group.smartsheet.model")
generatorName.set("java") // language for client (duh)
library.set("native") // the HTTP client lib; see java-generator docs for full list
generateApiTests.set(true)
generateApiDocumentation.set(false) // for now no point
generateModelDocumentation.set(false) // for now no point
configOptions.set(mutableMapOf(
"openApiNullable" to "false", // OpenAPI Jackson Nullable library (not needed?)
"hideGenerationTimestamp" to "true", // seems kinda pointless
"generateBuilders" to "true",
))
}
because of generatorName.set("java")
these parameters are eventually passed into org.openapitools.codegen.languages.JavaClientCodegen#processOpts
where much of the customized processing occurs (determining which features, templates, etc to enable/disable based on the various options which have been stored into instance variables of the JavaClientCodegen
instance).
the hierarchy is rather deep and complicated but given the wide range of languages supported i guess it's inevitable that this project would be somewhat complicated.
-
JavaClientCodegen
- extends
AbstractJavaCodegen
- extends
DefaultCodegen
- implements
CodegenConfig
- lots of language-agnostic settings
- mustache settings and lambdas for pluggable functionality
- default type mapping (which doesn't seem language-agnostic to me)
- setting/property conversion
- ...
- implements
- implements
CodegenConfig
- utility method signatures and getters and setters for a huge number of settings
void processOpts()
- implements
DocumentationProviderFeatures
- additional properties to select the documentation provider and the annotation library to use during code generation
- HUGE amount of features here ... TODO
- extends
- implements
BeanValidationFeatures
(Language supports generating BeanValidation-Annotations)void setUseBeanValidation(boolean useBeanValidation)
- implements
PerformBeanValidationFeatures
(Language supports performing BeanValidation)void setPerformBeanValidation(boolean performBeanValidation)
- implements
GzipFeatures
void setUseGzipFeature(boolean useGzipFeature)
- extends