📖 Documentation · 🚀 Getting started · ⚙️ Configuration · 💡 Recipes · ⬆️ Migrating from 1.x · 🍃 springdoc-openapi
If you ❤️ springdoc-openapi, become a sponsor: it covers the project expenses and helps it grow.
springdoc-openapi-gradle-plugin writes the OpenAPI description of your application to a file during the build, so you can commit it, diff it, publish it, or feed it to code generators. ✨
It starts your Spring Boot application in the background with the same settings as bootRun, downloads the
description that springdoc-openapi serves at /v3/api-docs, and
stops the application again. Because the description comes from the running application, it is exactly what
springdoc-openapi serves at runtime. When nothing changed since the last run, the task is up to date and the
application is not started at all.
Add the plugin next to the Spring Boot plugin, in your application's build file:
Kotlin DSL (build.gradle.kts) | Groovy DSL (build.gradle) |
|---|---|
plugins {
java
id("org.springframework.boot") version "3.5.16"
id("org.springdoc.openapi-gradle-plugin") version "2.0.0"
} |
plugins {
id 'java'
id 'org.springframework.boot' version '3.5.16'
id 'org.springdoc.openapi-gradle-plugin' version '2.0.0'
} |
Your application needs springdoc-openapi itself (for example org.springdoc:springdoc-openapi-starter-webmvc-api), so
that it serves the description. Then run:
./gradlew generateOpenApiDocs👉 The description is written to build/openapi.json.
Tip
Check the Gradle Plugin Portal for the latest version.
The plugin only calls an HTTP endpoint of your application, so it works with any version of springdoc-openapi:
| Spring Boot | springdoc-openapi |
|---|---|
| 🍃 4.x | 3.x |
| 🍃 3.x | 2.x |
| 🍂 2.x | 1.x |
The plugin needs Gradle 8.0 or later, and is tested up to Gradle 9.8, in builds written with the Kotlin or the Groovy DSL. It runs on every Java version that your Gradle version supports (Java 8 and later for Gradle 8, Java 17 and later for Gradle 9).
| Task | Description |
|---|---|
generateOpenApiDocs |
Starts the application, downloads its OpenAPI description, writes it to a file and stops the application |
The task is up to date, and does not start the application, when the classpath and the settings of the application
(main class, arguments, JVM arguments, system properties, Java toolchain) and the openApi configuration did not
change. It supports the configuration cache.
The build must apply the Spring Boot plugin (org.springframework.boot) and the java plugin (or the Kotlin plugin),
in any order: the application is started with the settings of their bootRun task.
Everything is configured in the openApi block. All the parameters are optional.
| Parameter | Default | Description |
|---|---|---|
apiDocsUrl |
http://localhost:8080/v3/api-docs |
URL of the OpenAPI description. If it ends with .yaml (for example /v3/api-docs.yaml), the file is written as YAML |
outputDir |
build |
Directory of the generated file |
outputFileName |
openapi.json |
Name of the generated file |
waitTimeInSeconds |
30 |
How long to wait for the application to start and serve apiDocsUrl |
groupedApiMappings |
none | Map of URL to file name, to write one file per group. When set, apiDocsUrl and outputFileName are ignored |
requestHeaders |
none | HTTP headers sent with the request, for example for authentication or x-forwarded-* headers |
trustStore |
none | Path to a trust store with the certificate of an application served over HTTPS |
trustStorePassword |
none | Password of the trust store |
customBootRun |
the settings of bootRun |
Settings used to start the application, see below |
| Kotlin DSL | Groovy DSL |
|---|---|
openApi {
apiDocsUrl.set("http://localhost:9090/v3/api-docs")
outputDir.set(layout.buildDirectory.dir("docs"))
outputFileName.set("swagger.json")
waitTimeInSeconds.set(60)
requestHeaders.set(mapOf(
"x-forwarded-host" to "api.example.com",
"x-forwarded-port" to "443"
))
customBootRun {
args.set(listOf("--server.port=9090"))
}
} |
openApi {
apiDocsUrl = 'http://localhost:9090/v3/api-docs'
outputDir = layout.buildDirectory.dir('docs')
outputFileName = 'swagger.json'
waitTimeInSeconds = 60
requestHeaders = [
'x-forwarded-host': 'api.example.com',
'x-forwarded-port': '443'
]
customBootRun {
args = ['--server.port=9090']
}
} |
Note
A JSON description is pretty-printed before it is written. A YAML description is written exactly as served. The output of the application is shown in the build output.
By default, the application is started with the settings of your bootRun task. Use customBootRun to start it
differently when generating the docs, for example with another profile. Each property that you set replaces the
bootRun one, and the others still come from bootRun:
| Property | Description |
|---|---|
args |
Arguments of the application, for example --spring.profiles.active=openapi |
jvmArgs |
JVM arguments |
systemProperties |
System properties |
environment |
Environment variables |
mainClass |
Main class |
classpath |
Classpath |
workingDir |
Working directory |
Like with bootRun, the application runs in the project directory (so compose.yaml or a config/ directory are
found) and with the Java toolchain of bootRun.
-
🏷️ A profile for the docs: start the application with a profile that, for example, disables external services:
openApi { customBootRun { args.set(listOf("--spring.profiles.active=openapi")) } } -
⌨️ Settings from the command line: pass the Gradle system properties to the application with
customBootRun { systemProperties.set(System.getProperties().entries.associate { it.key.toString() to it.value }) }(Groovy:systemProperties = System.properties), then run./gradlew generateOpenApiDocs -Dspring.profiles.active=openapi. -
📄 YAML: point
apiDocsUrltohttp://localhost:8080/v3/api-docs.yamland setoutputFileNametoopenapi.yaml. -
🗂️ Groups: write one file per group:
openApi { groupedApiMappings.set(mapOf( "http://localhost:8080/v3/api-docs/public" to "openapi-public.json", "http://localhost:8080/v3/api-docs/admin" to "openapi-admin.json" )) } -
🔒 HTTPS: if your application only serves HTTPS with a certificate that Java does not trust, create a trust store with its certificate and set
trustStoreandtrustStorePassword:keytool -import -noprompt -alias ca -file ca.crt -keystore truststore.p12 -deststoretype PKCS12 -storepass changeit
-
🐳 Testcontainers (
bootTestRun): start the test main class of Spring Boot's Testcontainers support with the test classpath:openApi { customBootRun { mainClass.set("com.example.TestApplication") classpath.from(sourceSets.main.get().runtimeClasspath, sourceSets.test.get().runtimeClasspath) } } -
🏗️ As part of the build:
tasks.named("build") { finalizedBy("generateOpenApiDocs") }.
Tip
If the build fails with The application exited with code …, the application could not start: its output above
tells why. With Unable to connect to … waited for 30 seconds, the application is still starting or does not serve
apiDocsUrl: check the URL, or increase waitTimeInSeconds. With Another process is already listening on …,
stop the other process, for example an application left running by another build.
Version 2.0 starts and stops the application inside generateOpenApiDocs, instead of with separate tasks of the
execfork plugin:
- 🗑️ The
forkedSpringBootRunandforkedSpringBootStoptasks are gone, and the execfork plugin is no longer applied. Remove the configuration of these tasks from your build. If you used them to add a dependency, add it togenerateOpenApiDocs, although this is rarely needed now: the task depends on the tasks that build the classpath of the application. - 🧹 These 1.x workarounds are no longer needed, and can be removed:
customBootRun { workingDir.set(projectDir) }: the application runs in the project directory again (#150);dependsOn("assemble")ordependsOn("testClasses")onforkedSpringBootRun(#164);notCompatibleWithConfigurationCache(...)on the plugin tasks: the configuration cache is supported (#153);- applying the
javaorkotlinplugin before this one (#121), or applyingcom.github.psxpaul.execforkyourself for a script plugin (#169).
- 🔄 The settings of the application are now inputs of
generateOpenApiDocs: changing its arguments, for example its profile, regenerates the description. The application is not started when the task is up to date. - 🛑 The build fails as soon as the application exits, and before starting it if another process already listens on
the port of
apiDocsUrl. - 📝
nullvalues of a JSON description are kept. - 🍃 Since 2.1, the plugin no longer applies the Spring Boot plugin itself: apply
org.springframework.bootin your build, as in Getting started.
- 📖 Read the plugin documentation and the springdoc-openapi documentation
- 🙋 Ask questions on Stack Overflow with the
springdoctag - 🐛 Report bugs in GitHub issues, with a minimal reproducer
Note
springdoc-openapi is a community project, not maintained by the Spring team.
Contributions are welcome! See CONTRIBUTING.adoc and the Code of Conduct.
To build the plugin (tests and detekt) and install it in your local Maven repository:
./gradlew build publishToMavenLocalTo try it in an application, use the version from build.gradle.kts in the application's plugins block, and resolve
plugins from your local Maven repository first in its settings.gradle(.kts):
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
}
}Thanks to all our contributors 🙏
Special thanks to JetBrains for their support.
springdoc-openapi-gradle-plugin is Open Source software released under the Apache 2.0 license.

