openapi-generator-original/modules/openapi-generator-gradle-plugin
Leon Linhart 0edcc9d204
Correctly annotate Gradle task in- & outputs and enable stricter plugin validation (#21957)
* Correctly apply Gradle task input & output annotations to accessors

Gradle's task input and output annotations should be applied to the accessors instead of the properties. No adhering to this can cause funky behavior in the generated stubs. Examples of this can be found in the docs: https://docs.gradle.org/current/userguide/implementing_custom_tasks.html

Also adds missing annotations so that validation passes

* Enable strict Gradle plugin validation
2025-09-13 16:49:06 +08:00
..
2025-08-22 19:17:23 +08:00

= OpenAPI Generator Gradle Plugin

This document describes the Gradle plugin for OpenAPI Generator.

This Gradle plugin offers a declarative DSL via _extensions_ (these are Gradle project extensions).
These map almost fully 1:1 with the options you'd pass to the CLI or Maven plugin. The plugin maps the extensions to a task of the same name to provide a clean API. If you're interested in the extension/task mapping concept from a high-level, you can https://docs.gradle.org/current/userguide/custom_plugins.html#sec:mapping_extension_properties_to_task_properties[check out Gradle's docs].

== Tasks

Tasks are listed under the "OpenAPI Tools" tasks heading.

.OpenAPI Tools Tasks
|===
|task name |description

|*openApiGenerate*
|Generate code via Open API Tools Generator for Open API 2.0 or 3.x specification documents.

|*openApiGenerators*
|Lists generators available via Open API Generators.

|*openApiMeta*
|Generates a new generator to be consumed via Open API Generator.

|*openApiValidate*
|Validates an Open API 2.0 or 3.x specification document.
|===


[NOTE]
====
The plugin implements the above tasks as project extensions of the same name. If you'd like to declare
these tasks as dependencies to other tasks (using `dependsOn`), you'll need  a task reference. e.g.:

```
compileJava.dependsOn tasks.openApiGenerate
```
====

All extensions can be rewritten as tasks. Where you can have only a single extension defined in your Gradle file, you may have multiple tasks.

.One Extension, multiple tasks
[source,groovy]
----
// Validating a single specification
openApiValidate {
    inputSpec.set("$rootDir/petstore-v3.0-invalid.yaml")
}

// Define a task for validating one specification
task validateGoodSpec(type: org.openapitools.generator.gradle.plugin.tasks.ValidateTask) {
    inputSpec.set("$rootDir/petstore-v3.0.yaml")
}

// Define a task for validating another specification
task validateBadSpec(type: org.openapitools.generator.gradle.plugin.tasks.ValidateTask) {
    inputSpec.set("$rootDir/petstore-v3.0-invalid.yaml")
}

// Define a task for batch validations
task validateSpecs(dependsOn: ['validateGoodSpec', 'validateBadSpec'])
----

[NOTE]
====
The tasks support Gradle Up-To-Date checking and Gradle Cache. Enable caching globally by setting `org.gradle.caching=true` in the `gradle.settings`
file or by passing the command line property `--build-cache` when executing on the command line.

Disable up-to-date checks and caching by setting the following property when using the extension:

.Disable caching for extension
[source,groovy]
----
tasks.withType(org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
    outputs.upToDateWhen { false }
    outputs.cacheIf { false }
}
----
Disable up-to-date checks and caching for a custom task:

.Disable caching for custom task
[source,groovy]
----
task validateGoodSpec(type: org.openapitools.generator.gradle.plugin.tasks.ValidateTask) {
    outputs.upToDateWhen { false }
    outputs.cacheIf { false }

    inputSpec.set("$rootDir/petstore-v3.0.yaml")
}
----
====

== Plugin Setup

//# RELEASE_VERSION

[source,group]
----
plugins {
  id "org.openapi.generator" version "7.15.0"
}
----

Using https://docs.gradle.org/current/userguide/plugins.html#sec:old_plugin_application[legacy plugin application]:

[source,groovy]
----
buildscript {
  repositories {
    mavenLocal()
    mavenCentral()
    // or, via Gradle Plugin Portal:
    // url "https://plugins.gradle.org/m2/"
  }
  dependencies {
    classpath "org.openapitools:openapi-generator-gradle-plugin:7.15.0"
  }
}

apply plugin: 'org.openapi.generator'
----
//# /RELEASE_VERSION

== Configuration

=== openApiGenerate

.Options
|===
|Key |Data Type |Default |Description

|verbose
|Boolean
|false
|The verbosity of generation

|validateSpec
|Boolean
|true
|Whether or not we should validate the input spec before generation. Invalid specs result in an error.

|generatorName
|String
|None
|The name of the generator which will handle codegen.

|outputDir
|String
|None
|The output target directory into which code will be generated.

|inputSpec
|String
|None
|The Open API 2.0/3.x specification location.

|inputSpecRootDirectory
|String
|None
|Local root folder with spec file(s)

|mergedFileName
|String
|None
|Name of the file that will contain all merged specs

|remoteInputSpec
|String
|None
|The remote Open API 2.0/3.x specification URL location.

|templateDir
|String
|None
|The template directory holding a custom template.

|templateResourcePath
|String
|None
|Directory with mustache templates via resource path. This option will overwrite any option defined in `templateDir`

|auth
|String
|None
|Adds authorization headers when fetching the OpenAPI definitions remotely. Pass in a URL-encoded string of name:header with a comma separating multiple values.

|globalProperties
|Map(String,String)
|None
|Sets specified global properties.

|configFile
|String
|None
|Path to json configuration file. See OpenAPI Generator readme for structure details.

|skipOverwrite
|Boolean
|false
|Specifies if the existing files should be overwritten during the generation.

|packageName
|String
|(generator specific)
|Package for generated classes (where supported).

|apiPackage
|String
|(generator specific)
|Package for generated api classes.

|modelPackage
|String
|(generator specific)
|Package for generated model classes.

|modelNamePrefix
|String
|None
|Prefix that will be prepended to all model names.

|modelNameSuffix
|String
|None
|Suffix that will be appended to all model names.

|apiNameSuffix
|String
|None
|Suffix that will be appended to all api names.

|instantiationTypes
|Map(String,String)
|None
|Sets instantiation type mappings.

|typeMappings
|Map(String,String)
|None
|Sets mappings between OpenAPI spec types and generated code types in the format of OpenAPIType=generatedType,OpenAPIType=generatedType. For example: `array=List,map=Map,string=String`. You can also have multiple occurrences of this option. To map a specified format, use type+format, e.g. string+password=EncryptedString will map `type: string, format: password` to `EncryptedString`.

|schemaMappings
|Map(String,String)
|None
|specifies mappings between the schema and the new name in the format of schema_a=Cat,schema_b=Bird. https://openapi-generator.tech/docs/customization/#schema-mapping

|nameMappings
|Map(String,String)
|None
|specifies mappings between the property name and the new name in the format of property_a=firstProperty,property_b=secondProperty. https://openapi-generator.tech/docs/customization/#name-mapping

|modelNameMappings
|Map(String,String)
|None
|specifies mappings between the model name and the new name in the format of model_a=FirstModel,property_b=SecondModel. https://openapi-generator.tech/docs/customization/#name-mapping

|parameterNameMappings
|Map(String,String)
|None
|specifies mappings between the parameter name and the new name in the format of parameter_a=firstParameter,parameter_b=secondParameter. https://openapi-generator.tech/docs/customization/#name-mapping

|inlineSchemaNameMappings
|Map(String,String)
|None
|specifies mappings between the inline schema name and the new name in the format of inline_object_2=Cat,inline_object_5=Bird.

|inlineSchemaOptions
|Map(String,String)
|None
|specifies the options used when handling inline schema in inline model resolver

|additionalProperties
|Map(String,Any)
|None
|Sets additional properties that can be referenced by the mustache templates.

|serverVariables
|Map(String,String)
|None
|Sets server variable for server URL template substitution, in the format of name=value,name=value. You can also have multiple occurrences of this option.

|languageSpecificPrimitives
|List(String)
|None
|Specifies additional language specific primitive types in the format of type1,type2,type3,type3. For example: String,boolean,Boolean,Double.

|importMappings
|Map(String,String)
|None
|Specifies mappings between a given class and the import that should be used for that class.

|invokerPackage
|String
|None
|Root package for generated code.

|groupId
|String
|None
|GroupId in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.

|id
|String
|None
|ArtifactId in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.

|version
|String
|None
|Artifact version in generated pom.xml/build.gradle or other build script. Language-specific conversions occur in non-jvm generators.

|library
|String
|None
|Reference the library template (sub-template) of a generator.

|gitHost
|String
|github.com
|Git user ID, e.g. gitlab.com.

|gitUserId
|String
|None
|Git user ID, e.g. openapitools.

|gitRepoId
|String
|None
|Git repo ID, e.g. openapi-generator.

|releaseNote
|String
|'Minor update'
|Release note.

|httpUserAgent
|String
|None
|HTTP user agent, e.g. codegen_csharp_api_client. Generator default is 'OpenAPI-Generator/{packageVersion}/{language}', but may be generator-specific.

|reservedWordsMappings
|Map(String,String)
|None
|Specifies how a reserved name should be escaped to. Otherwise, the default _<name> is used.

|ignoreFileOverride
|String
|None
|Specifies an override location for the .openapi-generator-ignore file. Most useful on initial generation.

|removeOperationIdPrefix
|Boolean
|false
|Remove prefix of operationId, e.g. config_getId => getId.

|skipOperationExample
|Boolean
|false
|Skip examples defined in the operation

|apiFilesConstrainedTo
|List(String)
|None
|Defines which API-related files should be generated. This allows you to create a subset of generated files (or none at all). See Note Below.

|modelFilesConstrainedTo
|List(String)
|None
|Defines which model-related files should be generated. This allows you to create a subset of generated files (or none at all). See Note Below.

|supportingFilesConstrainedTo
|List(String)
|None
|Defines which supporting files should be generated. This allows you to create a subset of generated files (or none at all). See Note Below.

|generateModelTests
|Boolean
|true
|Defines whether or not model-related _test_ files should be generated.

|generateModelDocumentation
|Boolean
|true
|Defines whether or not model-related _documentation_ files should be generated.

|generateApiTests
|Boolean
|true
|Defines whether or not api-related _test_ files should be generated.

|generateApiDocumentation
|Boolean
|true
|Defines whether or not api-related _documentation_ files should be generated.

|configOptions
|Map(String,String)
|None
|A map of options specific to a generator. To see the full list of generator-specified parameters, please refer to https://github.com/OpenAPITools/openapi-generator/blob/master/docs/generators.md[generators docs]. Note that any config options from a generator specific document may go here, and some generators may duplicate other options which are siblings to `configOptions`.

|logToStderr
|Boolean
|false
|To write all log messages (not just errors) to STDOUT

|enablePostProcessFile
|Boolean
|false
|To enable the file post-processing hook. This enables executing an external post-processor (usually a linter program). This only enables the post-processor. To define the post-processing command, define an environment variable such as LANG_POST_PROCESS_FILE (e.g. GO_POST_PROCESS_FILE, SCALA_POST_PROCESS_FILE). Please open an issue if your target generator does not support this functionality.

|skipValidateSpec
|Boolean
|false
|To skip spec validation. When true, we will skip the default behavior of validating a spec before generation.

|openapiNormalizer
|Map(String,String)
|None
|specifies the rules to be enabled in OpenAPI normalizer in the form of RULE_1=true,RULE_2=original.

|generateAliasAsModel
|Boolean
|false
|To generate alias (array, list, map) as model. When false, top-level objects defined as array, list, or map will result in those definitions generated as top-level Array-of-items, List-of-items, Map-of-items definitions. When true, A model representation either containing or extending the array,list,map (depending on specific generator implementation) will be generated.

|engine
|String
|mustache
|Templating engine: "mustache" (default) or "handlebars" (beta)

|cleanupOutput
|Boolean
|false
|Defines whether the output directory should be cleaned up before generating the output.

|dryRun
|Boolean
|false
|Defines whether the generator should run in dry-run mode. In dry-run mode no files are written and a summary about
file states is output.
|===

[NOTE]
====
Configuring any one of `apiFilesConstrainedTo`, `modelFilesConstrainedTo`, or `supportingFilesConstrainedTo` results
in others being disabled. That is, OpenAPI Generator considers any one of these to define a subset of generation.

For more control over generation of individual files, configure an ignore file and refer to it via `ignoreFileOverride`.
====

[NOTE]
====
When configuring `globalProperties` in order to perform selective generation you can disable generation of some parts by providing `"false"` value:
[source,groovy]
----
openApiGenerate {
    // other settings omitted
    globalProperties.set([
        modelDocs: "false",
        apis: "false"
    ])
}
----
When enabling generation of only specific parts you either have to provide CSV list of what you particularly are generating or provide an empty string `""` to generate everything. If you provide `"true"` it will be treated as a specific name of model or api you want to generate.
[source,groovy]
----
openApiGenerate {
    // other settings omitted
    globalProperties.set([
        apis: "",
        models: "User:Pet"
    ])
}
----
====

=== openApiValidate

.Options
|===
|Key |Data Type |Default |Description

|inputSpec
|String
|None
|The input specification to validate. Supports all formats supported by the Parser.

|recommend
|Boolean
|true
|Whether or not to offer recommendations related to the validated specification document.

|===

=== openApiMeta

.Options
|===
|Key |Data Type |Default |Description

|generatorName
|String
|None
|The human-readable generator name of the newly created template generator.

|packageName
|String
|org.openapitools.codegen
|The packageName generatorName to put the main class into.

|outputFolder
|String
|Current Directory
|Where to write the generated files

|===

=== openApiGenerators

.Options
|===
|Key |Data Type |Default |Description

|include
|String[]
|None
|A list of stability indexes to include (values: all,beta,stable,experimental,deprecated). Excludes deprecated by default.

|===

== Examples

=== openApiGenerate

This task exposes all options available via OpenAPI Generator CLI and the OpenAPI Generator Maven Plugin.

.in build.gradle
[source,groovy]
----
openApiGenerate {
    generatorName.set("kotlin")
    inputSpec.set("$rootDir/specs/petstore-v3.0.yaml")
    outputDir.set("$buildDir/generated")
    apiPackage.set("org.openapi.example.api")
    invokerPackage.set("org.openapi.example.invoker")
    modelPackage.set("org.openapi.example.model")
    configOptions.put("dateLibrary", "java8")
}
----

The above code demonstrates configuration of global options as well as generator-specific config options.

=== openApiGenerators

This is an output-only listing task. There's no need to add configuration to build.gradle.

.Example output of openApiGenerators task
[source,terminal]
----
$ ./gradlew openApiGenerators

> Task :openApiGenerators
The following generators are available:

CLIENT generators:
    - ada
…

SERVER generators:
    - ada-server
…

DOCUMENTATION generators:
    - cwiki
…

CONFIG generators:
    - apache2

OTHER generators:
…

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
----

[NOTE]
====
Generator type listings in the above example have been truncated to avoid potential confusion with changing generator support.

Please run the above task to list all available generators.
====

=== openApiMeta

.in build.gradle
[source,groovy]
----
openApiMeta {
   generatorName.set("Jim")
   packageName.set("us.jimschubert.example")
}
----

.Example output of openApiMeta task
[source,terminal]
----
$ ./gradlew openApiMeta

> Task :openApiMeta
Wrote file to /Users/jim/my_project/pom.xml
Wrote file to /Users/jim/my_project/src/main/java/us/jimschubert/example/JimGenerator.java
Wrote file to /Users/jim/my_project/README.md
Wrote file to /Users/jim/my_project/src/main/resources/jim/api.mustache
Wrote file to /Users/jim/my_project/src/main/resources/jim/model.mustache
Wrote file to /Users/jim/my_project/src/main/resources/jim/myFile.mustache
Wrote file to /Users/jim/my_project/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
Created generator JimGenerator

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
----


=== openApiValidate

.in build.gradle
[source,groovy]
----
openApiValidate {
   inputSpec.set("/src/openapi-generator/modules/openapi-generator/src/test/resources/3_0/petstore.yaml")
   recommend.set(true)
}
----

.Example output of openApiValidate task (success)
[source,terminal]
----
$ ./gradlew openApiValidate --input=/Users/jim/projects/openapi-generator/modules/openapi-generator/src/test/resources/3_0/ping.yaml

> Task :openApiValidate
Validating spec /Users/jim/projects/openapi-generator/modules/openapi-generator/src/test/resources/3_0/ping.yaml
Spec is valid.

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
----

.Example output of openApiValidate task (failure)
[source,terminal]
----
$ ./gradlew openApiValidate

> Task :openApiValidate FAILED
Validating spec /Users/jim/projects/openapi-generator/modules/openapi-generator/src/test/resources/3_0/petstore.yaml

Spec is invalid.
Issues:

        attribute info is missing


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':openApiValidate'.
> Validation failed.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

----

.in terminal (alternate)
[source,terminal]
----
$ ./gradlew openApiValidate --input=/Users/jim/projects/openapi-generator/modules/openapi-generator/src/test/resources/3_0/petstore.yaml
----

=== Generate multiple sources

If you want to perform multiple generation tasks, you'd want to create a task that inherits from the `GenerateTask`.
Examples can be found in https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator-gradle-plugin/samples/local-spec/build.gradle[samples/local-spec/build.gradle].

You can define any number of generator tasks; the generated code does _not_ need to be a JVM language.

```gradle
task buildGoClient(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
    generatorName.set("go")
    inputSpec.set("$rootDir/petstore-v3.0.yaml")
    additionalProperties.set([
            packageName: "petstore"
    ])
    outputDir.set("$buildDir/go")
    configOptions.set([
            dateLibrary: "threetenp"
    ])
}
task buildKotlinClient(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
    generatorName.set("kotlin")
    inputSpec.set("$rootDir/petstore-v3.0.yaml")
    outputDir.set("$buildDir/kotlin")
    apiPackage.set("org.openapitools.example.api")
    invokerPackage.set("org.openapitools.example.invoker")
    modelPackage.set("org.openapitools.example.model")
    configOptions.set([
            dateLibrary: "java8"
    ])
    globalProperties.set([
            modelDocs: "false"
    ])
}
```

To execute your specs, you'd then do:

```
./gradlew buildGoClient buildKotlinClient
```

If you want to simplify the execution, you could create a new task with `dependsOn`.

```gradle
task codegen(dependsOn: ['buildGoClient', 'buildKotlinClient'])
```

Or, if you're generating the code on compile, you can add these as a dependency to `compileJava` or any other existing task.
You can also mix the default task `openApiGenerate` with custom tasks:

```gradle
compileJava.dependsOn buildKotlinClient, tasks.openApiGenerate
```

[NOTE]
====
`openApiGenerate` is a project extension _and_ a task. If you want to use this in `dependsOn`,
you need a task reference or instance. One way to do this is to access it as `tasks.openApiGenerate`.

You can run `gradle tasks --debug` to see this registration.
====

== Troubleshooting

=== Android Studio

Android Studio may experience a Windows-specific Guava dependency conflict with openapi-generator-gradle-plugin versions greater than 3.0.0.

As a workaround, you may force exclude conflicting Guava dependencies.

//# RELEASE_VERSION
```gradle
buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
        classpath('org.openapitools:openapi-generator-gradle-plugin:7.15.0') {
            exclude group: 'com.google.guava'
        }
    }
}
// …

configurations {
    compile.exclude module: 'guava-jdk5'
}
// …
apply plugin: 'org.openapi.generator'
```
//# /RELEASE_VERSION

See https://github.com/OpenAPITools/openapi-generator/issues/1818[OpenAPITools/openapi-generator#1818] for more details.