Home›Java›Swagger & OpenAPI 3 in Spring Boot: springdoc-openapi 2.x Complete Guide
Intermediate
6 min · May 23, 2026
Swagger & OpenAPI 3 in Spring Boot: springdoc-openapi 2.x Complete Guide
Master Swagger/OpenAPI 3 in Spring Boot with springdoc-openapi 2.x, @Operation, @Schema, JWT security schemes, API grouping, and production-ready documentation..
N
NarenFounder & Principal Engineer
20+ years shipping production Java in banking & fintech. Notes here come from systems that actually shipped.
Add springdoc-openapi-starter-webmvc-ui 2.x dependency — no springfox, it's dead
Annotate controllers with @Operation, @ApiResponse, and models with @Schema for rich docs
Configure JWT Bearer security scheme in a @BeanOpenAPI config — not per-controller
Use @RouterOperation for functional endpoints; springdoc auto-discovers @RestController by default
Group APIs with GroupedOpenApi beans and expose /v3/api-docs/group-name per team or domain
✦ Definition~90s read
What is API Documentation with Swagger/OpenAPI?
OpenAPI 3 (formerly Swagger) is a language-agnostic specification for describing HTTP APIs. A valid OpenAPI document describes every endpoint's path, HTTP method, parameters, request body schema, possible responses, and authentication requirements in either JSON or YAML format.
★
OpenAPI is like a restaurant menu — it tells customers exactly what dishes (endpoints) are available, what ingredients (request parameters) each dish requires, and what they'll get back (responses).
Tools like Swagger UI render this spec as interactive documentation; code generators like OpenAPI Generator use it to produce client libraries.
springdoc-openapi 2.x is a Spring Boot library that generates an OpenAPI 3 spec automatically by scanning your @RestController classes at runtime. It reads @RequestMapping, @PathVariable, @RequestParam, @RequestBody, and return types to build the spec automatically.
You add annotations like @Operation and @ApiResponse to enrich the auto-generated spec with human-readable descriptions, examples, and error documentation.
The generated spec is served at /v3/api-docs (JSON) and /v3/api-docs.yaml (YAML). Swagger UI is served at /swagger-ui/index.html. Both paths are configurable and should be secured or disabled in production — the spec can expose your entire API surface to attackers.
Plain-English First
OpenAPI is like a restaurant menu — it tells customers exactly what dishes (endpoints) are available, what ingredients (request parameters) each dish requires, and what they'll get back (responses). Swagger UI is the waiter who presents that menu in a friendly, interactive way so you can actually order (test) without writing code.
You've just onboarded three new frontend developers and a mobile team. They spend three days reverse-engineering your API by reading source code and firing random requests because the documentation is either outdated, missing, or locked in a Confluence page that hasn't been touched since 2022. That three-day onboarding tax is multiplied across every integration partner, every new hire, and every support ticket. Good API documentation pays for itself in hours.
Springfox was the de facto Spring Boot documentation tool for years, but development stalled after Spring Boot 2.6 broke its URL matching strategy and it was never properly updated for Spring Boot 3. Continuing to use springfox in 2024 means fighting with classpath conflicts, broken security scheme rendering, and missing OpenAPI 3.1 features. springdoc-openapi is the correct answer for Spring Boot 3.x.
But documentation is not just developer convenience. OpenAPI specs are machine-readable contracts. They power code generators that create client SDKs in 20 languages from a single YAML file. They enable contract testing with tools like Pact. They feed into API gateways like Kong and AWS API Gateway for automatic routing and authentication enforcement. A well-maintained OpenAPI spec is a core infrastructure asset.
The difference between a useful API spec and a noise-filled spec comes down to discipline: documenting error responses, providing realistic examples, marking deprecated fields, and keeping the spec in sync with the code. springdoc-openapi makes keeping it in sync nearly automatic — but the quality of the human-written annotations determines whether the spec is genuinely useful.
This guide covers the full springdoc-openapi 2.x setup: dependency configuration, annotation best practices, JWT Bearer security scheme, multi-group API organization, hiding internal endpoints, and CI validation with the OpenAPI Gradle plugin.
Getting Started: Dependency and Auto-Configuration
springdoc-openapi 2.x integrates with Spring Boot 3.x auto-configuration. Adding a single dependency triggers the entire Swagger/OpenAPI setup with sensible defaults. No @EnableSwagger2 annotation, no Docket bean, no XML configuration. The library scans all @RestController beans on startup and builds the OpenAPI spec lazily on the first request to /v3/api-docs.
The critical version match: springdoc-openapi-starter-webmvc-ui version 2.x is for Spring Boot 3.x (Jakarta EE). Version 1.x is for Spring Boot 2.x (javax). Mixing them causes ClassNotFoundException at startup. Check the springdoc version compatibility matrix before every Spring Boot upgrade.
For reactive Spring WebFlux applications, use springdoc-openapi-starter-webflux-ui instead. For applications with both MVC and WebFlux, you need both. For Spring Boot applications without a web UI (just the API doc endpoint), use springdoc-openapi-starter-webmvc-api to exclude the Swagger UI static resources from the JAR.
After adding the dependency, visit http://localhost:8080/swagger-ui/index.html. You should see a fully functional Swagger UI with all your controllers documented. The spec is also available at /v3/api-docs (JSON) and /v3/api-docs.yaml. Configure the title, version, and description by adding an OpenAPI Spring bean.
Disable OpenAPI Docs in Production
Set springdoc.api-docs.enabled=false and springdoc.swagger-ui.enabled=false in your production configuration. The spec exposes your entire API surface. If you need docs accessible in prod, put them behind authentication.
Production Insight
Add a security integration test that GETs /v3/api-docs and asserts a 403 in the prod profile — catches accidental re-enablement in config PRs.
Key Takeaway
One dependency, zero XML, but always disable the docs endpoint in production — the spec is a roadmap for attackers.
Auto-generated specs are a starting point, not a destination. Without annotations, springdoc generates technically correct but human-useless documentation: endpoint paths and types but no descriptions, no error response documentation, no examples, no deprecation notices. The annotations @Operation, @ApiResponse, @Parameter, and @RequestBody (from springdoc, not Spring) close this gap.
@Operation annotates a controller method and provides a summary (one-line description shown in the endpoint list) and description (multi-line Markdown shown when the endpoint is expanded). Always fill both. A good summary answers 'what does this do?' A good description answers 'when should I use this, what are the side effects, and what can go wrong?'
@ApiResponse documents possible HTTP response codes. Document at minimum: 200/201 (success), 400 (validation error), 401 (unauthenticated), 403 (unauthorized), 404 (not found), 422 (business rule violation), and 500 (server error). For each, provide a description and a content with an example response body. Undocumented error responses cause integration partners to hardcode 200-or-crash logic.
@Parameter annotates path variables, query params, and headers. Use it to add descriptions, mark required/optional, and provide example values. Example values are rendered in Swagger UI as pre-filled inputs — they reduce friction for developers trying the API for the first time.
Annotate deprecated endpoints with @Operation(deprecated = true) and include a migration note in the description explaining what to use instead and when the old endpoint will be removed.
Document All Error Responses
Every integration partner will eventually hit your 422 and 429 responses. If they're not documented, those partners will treat them as bugs and file support tickets. Document every possible status code with an example body.
Production Insight
Run a weekly CI check with openapi-diff against the previous week's spec — undocumented breaking changes are the #1 cause of partner integration incidents.
Key Takeaway
Document every response status code with descriptions and examples — auto-generated specs are structurally correct but humanly useless without annotations.
Request and response DTOs are the heart of your API contract. @Schema on model classes and fields adds descriptions, examples, format constraints, and deprecation markers to the generated spec. Well-annotated DTOs eliminate most onboarding questions from integration partners.
At the class level, @Schema(description = '...') adds a description to the schema object in the spec. At the field level, @Schema(description = '...', example = '...') adds field-level documentation and an example value that appears in Swagger UI's example request body. Use @Schema(requiredMode = RequiredMode.REQUIRED) to mark fields as required in the schema — this is separate from Bean Validation's @NotNull.
For enums, springdoc renders all enum values in the spec by default. Add @Schema(description = '...') to the enum class and to individual constants where the semantics aren't obvious. For complex enums (state machines), add a table in the class-level description explaining valid transitions.
For fields that accept multiple formats (e.g., a date that can be epoch millis or ISO 8601 string), document both with @Schema(description = 'Accepts epoch millis or ISO 8601', example = '2024-01-15T10:30:00Z'). Ambiguous formats in APIs are a permanent source of integration bugs.
Mark deprecated fields with @Schema(deprecated = true) and add a description explaining the replacement. Never remove deprecated fields without a major version bump — always deprecate first and give partners at least 6 months notice.
@Schema vs @NotNull — They're Independent
@Schema(requiredMode = REQUIRED) only affects the OpenAPI spec display. @NotNull / @NotBlank from Bean Validation actually enforces the constraint at runtime. Always use both where appropriate — one documents, the other enforces.
Production Insight
Add a CI step that compares the generated spec against a committed baseline — unexpected schema changes in a PR catch breaking changes before they reach partners.
Key Takeaway
Annotate every DTO field with description and example — without them, partners read your code to understand your API, which defeats the purpose of documentation.
thecodeforge.io
Spring Boot Swagger Openapi
JWT Bearer Security Scheme Configuration
Most production APIs use JWT Bearer token authentication. The OpenAPI security scheme configuration tells Swagger UI to show an Authorize button and attach the Bearer token to every request. Without this, developers must manually edit request headers in Swagger UI for every single request — frustrating and error-prone.
The security scheme is defined in the global OpenAPI bean under components.securitySchemes. The scheme name (e.g., bearerAuth) must match exactly in both the scheme definition and the @SecurityRequirement annotations on operations. Case sensitivity matters.
For APIs with both public and authenticated endpoints, don't apply the security requirement globally — apply it per-controller or per-method with @SecurityRequirement(name = 'bearerAuth'). Public endpoints (like login, signup, health check) should not show the padlock icon.
For APIs with multiple authentication methods (API key + JWT, or different token types for different consumer groups), define multiple security schemes and apply different ones to different groups of endpoints. springdoc supports OR (any one scheme) and AND (multiple required) security requirement configurations.
For OAuth2 flows, use SecurityScheme.Type.OAUTH2 with OAuthFlows. springdoc renders the full OAuth2 authorization code flow in Swagger UI, allowing developers to authenticate directly from the docs without copying tokens manually.
Token Entry in Swagger UI
In Swagger UI's Authorize dialog, enter only the token value — not 'Bearer token'. springdoc automatically prepends 'Bearer ' when the scheme is set to 'bearer'. Entering 'Bearer eyJ...' will result in 'Bearer Bearer eyJ...' and 401 errors.
Production Insight
Add a /auth/token/inspect endpoint (dev/staging only) that decodes and validates the JWT structure — saves hours of base64-decoding JWT headers in developer onboarding sessions.
Key Takeaway
Define JWT Bearer in the global OpenAPI bean; clear security on public endpoints explicitly; teach developers to enter only the token value in Swagger UI — not the Bearer prefix.
API Grouping with GroupedOpenApi
As APIs grow, a single Swagger UI showing 200+ endpoints from 15 different domains becomes unusable. GroupedOpenApi beans split the spec into logical groups, each with its own /v3/api-docs/{group-name} endpoint and its own Swagger UI tab. This is the production-grade approach for any API with more than 3-4 controllers.
Groups are defined by path prefix, package name, or annotation. Path prefix is the most common: /api/v1/ is one group, /api/v2/ is another. Package-based grouping works well for microservices where different teams own different controller packages.
Each GroupedOpenApi can have its own OpenApiCustomizer that applies group-specific metadata: a different title, a different base URL, additional servers, or group-specific security requirements. This lets you maintain a public API group (consumer-facing) and a private API group (partner/internal) with different security schemes and documentation depth.
For microservices using an API gateway, configure springdoc on the gateway to aggregate specs from multiple services using the urls configuration in Swagger UI. The gateway's Swagger UI shows specs from all downstream services in a single browser tab, making cross-service development dramatically easier.
Use @Hidden for Internal Endpoints
Annotate any endpoint that should not be in the public spec with @Hidden. This includes health check implementations, internal callback endpoints, and debug endpoints. Never rely on obscurity — pair @Hidden with Spring Security path restrictions.
Production Insight
Generate and commit the spec YAML in CI with mvn springdoc:generate and use openapi-diff in the pipeline — breaking changes to the public group spec fail the build automatically.
Key Takeaway
Use GroupedOpenApi to split large APIs into consumer/admin/partner groups; use @Hidden for all internal endpoints; use gateway URL aggregation for multi-service documentation.
Generating the Spec in CI and Contract Testing
Runtime spec generation is convenient for development but unreliable for CI/CD. A spec generated in a JVM with a mocked database is not guaranteed to match the running production service. The correct approach generates the spec as a build artifact, commits it to the repository, and validates every PR against it.
The springdoc-openapi-maven-plugin generates the spec at build time by starting the Spring context in a test profile. The output is a .json or .yaml file that can be committed to the repository. CI then uses openapi-diff to compare the committed spec against the newly generated one and fails the build if breaking changes are introduced without a version bump.
Contract testing with Pact uses the OpenAPI spec as the consumer contract. The provider (your Spring Boot service) runs Pact verifications against the spec in CI, ensuring every documented endpoint actually works as documented. This catches drift between annotations and implementation — the most common documentation bug.
For SDK generation, the committed spec feeds into openapi-generator-cli in a separate CI step that regenerates client libraries in TypeScript, Python, and Go. If the spec changes in a way that breaks client generation, CI catches it. The generated clients are published to an internal package registry.
Commit the OpenAPI Spec to the Repository
Treat openapi.yaml like generated source code — commit it, diff it in PRs, and fail CI on breaking changes. A committed spec enables SDK generation, contract testing, and API changelog generation in the release pipeline.
Production Insight
Use semantic-release or a similar tool to generate API changelogs from openapi-diff output automatically on every merge to main — partners subscribe to the changelog RSS feed instead of polling your Swagger UI.
Key Takeaway
Generate the spec in CI, commit it as an artifact, diff it in PRs with openapi-diff, and feed it to openapi-generator for SDK generation — this is the complete production API documentation pipeline.
Why Your Devs Are Yelling at the Swagger UI
Out of the box, Springdoc gives you a working Swagger UI. But the default config will sink you in production. You get every endpoint exposed, every schema dumped, and no way to control what hits the wire. That's a security incident waiting to happen. The fix is surgical: disable the UI in production profiles, control which groups are visible, and always set a custom path. Never expose /v3/api-docs or /swagger-ui/* to the open internet. Use springdoc.api-docs.enabled=false in your production profile and route through a gateway that enforces auth. Your QA team will thank you. Your security auditor will too.
Swagger UI only available on non-prod profiles. Two groups: v1 and internal.
Production Trap:
Leaving Swagger UI enabled in production is a top-10 OWASP misconfiguration. Attackers will crawl your exposed endpoints. Disable it per profile or lock it behind VPN.
Key Takeaway
Hide Swagger UI in production. Use profiles and custom paths. Control what is exposed, always.
JSR-303 Validation: The Silent Spec Killer
You spent hours annotating controllers with @Operation, @ApiResponse, and @Schema. That's fine, but you're duplicating work. Springdoc auto-discovers JSR-303 Bean Validation annotations (@NotNull, @Size, @Min, @Pattern) on your DTOs and injects them into the OpenAPI spec. No extra code needed. This means when you add @NotBlank on a field, Swagger UI shows 'required: true' and the minLength constraint automatically. If you change validation logic, the spec updates. No sync issues. But — only if you don't override it manually with @Schema. If you mix both, Springdoc prefers the explicit @Schema annotation. That's fine, but you lose the auto-sync. Pick one: use validation annotations for the contract, or use @Schema. Don't mix unless you're debugging something exotic.
UserDto.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// io.thecodeforge — java tutorial// Auto-discovered by Springdoc — no @Schema neededpublicclassUserDto {
@NotBlank(message = "Username is required")
@Size(min = 3, max = 20)
privateString username;
@NotNull
@EmailprivateString email;
@Min(18)
@Max(120)
privateint age;
// getters and setters omitted for brevity
}
Springdoc hooks into the Bean Validation metadata at startup. Every @NotNull, @Size, @Pattern becomes a schema constraint. No manual mapping. Less code rot.
Key Takeaway
Your validation annotations are your OpenAPI schema. Stop duplicating with @Schema unless you need to override.
● Production incidentPOST-MORTEMseverity: high
Security Breach: OpenAPI Spec Exposed in Production
Symptom
A security researcher reported that the company's internal admin endpoints (e.g., /internal/admin/users/{id}/override-kyc) were fully documented in the publicly accessible Swagger UI at api.company.com/swagger-ui/index.html.
Assumption
The team assumed Swagger UI was only accessible in dev because it was disabled via springdoc.swagger-ui.enabled=false in the dev profile, but they had no production-specific property file and the default was true.
Root cause
The production application.yml did not override the Swagger UI enabled flag. Additionally, internal endpoints annotated with @Hidden were missing from some controllers added by a new team member who was unaware of the convention. The spec was reachable without any authentication.
Fix
Immediately disabled Swagger UI and /v3/api-docs in production by setting springdoc.swagger-ui.enabled=false and springdoc.api-docs.enabled=false in the production configuration. Added a Spring Security rule to block /v3/api-docs/ and /swagger-ui/ in all environments. Implemented a separate internal documentation deployment behind the VPN.
Key lesson
Never expose OpenAPI docs in production without authentication.
Add a security integration test that asserts /v3/api-docs returns 403 in the production profile.
Use @Hidden on all internal endpoints and enforce it with an ArchUnit rule.
Production debug guideSymptom → root cause → fix5 entries
Symptom · 01
Swagger UI loads but shows 'No operations defined in spec'
→
Fix
springdoc failed to scan your controllers. Check: (1) your controllers are in a package scanned by Spring's component scan — if you moved them to a module not under the main application package, add springdoc.packages-to-scan configuration; (2) all controllers are annotated with @RestController or @Controller — plain @Component classes are not scanned; (3) the springdoc dependency version matches your Spring Boot version — use springdoc-openapi-starter-webmvc-ui 2.x for Spring Boot 3.x.
Symptom · 02
JWT Bearer token is not persisted between Swagger UI requests
→
Fix
The security scheme is either missing from the global OpenAPI bean or not applied to the operations. Check that your @Bean OpenAPI config includes a SecurityScheme of type HTTP with scheme 'bearer' and bearerFormat 'JWT'. Then verify operations are annotated with @SecurityRequirement(name = 'bearerAuth') or the requirement is applied globally via openAPI.addSecurityItem(). In Swagger UI, use the Authorize button and enter only the token — not 'Bearer token'.
Symptom · 03
@Schema annotations not rendering in the spec
→
Fix
Ensure the class is on the classpath that springdoc scans and is used as a request/response type somewhere in a controller. springdoc only includes schemas that are reachable from controller signatures. If you have a DTO that is only referenced via reflection or a generic wrapper, add it explicitly with springdoc.components.schemas config or annotate the field with @Schema in the enclosing class.
Symptom · 04
Circular reference exception when generating spec
→
Fix
A model references itself directly or through a chain (e.g., TreeNode has List<TreeNode> children). Add @Schema(description = '...') at the field level to help springdoc break the cycle, or configure springdoc to ignore the circular field with @JsonIgnore for spec generation only. Alternatively, set springdoc.writer-with-default-pretty-printer=true and check the /v3/api-docs output for the cycle path.
Symptom · 05
springdoc fails with ClassNotFoundException on startup after upgrade
→
Fix
springdoc-openapi 2.x requires Spring Boot 3.x and Jakarta EE (not javax). If you see ClassNotFoundException for javax.servlet.*, your application or a transitive dependency is still on the javax namespace. Check dependencies with mvn dependency:tree | grep javax. Upgrade all dependencies to their Jakarta-compatible versions.
★ Debug Cheat SheetFast commands to diagnose and fix OpenAPI/Swagger issues
kubectl get configmap app-config -o yaml | grep springdoc
Fix now
Set springdoc.api-docs.enabled=false and springdoc.swagger-ui.enabled=false in production config and redeploy immediately.
springfox vs springdoc-openapi
Feature
springfox (legacy)
springdoc-openapi 2.x
Spring Boot 3.x support
Broken (use workarounds)
Full native support
OpenAPI version
OpenAPI 2 (Swagger 2)
OpenAPI 3.1
Jakarta EE
No (javax only)
Yes
Auto-discovery
Requires @EnableSwagger2 + Docket
Zero config — just the dependency
Security schemes
Manual ApiKey/BasicAuth only
HTTP Bearer, OAuth2, OpenID Connect
Maintenance status
Abandoned (last release 2020)
Actively maintained
Functional endpoints
Not supported
Supported via @RouterOperation
Spring WebFlux
Limited
Full support (webflux starter)
⚙ Quick Reference
2 commands from this guide
File
Command / Code
Purpose
SwaggerSecurityConfig.java
@Configuration
Why Your Devs Are Yelling at the Swagger UI
UserDto.java
public class UserDto {
JSR-303 Validation
Key takeaways
1
Use springdoc-openapi 2.x for Spring Boot 3.x
springfox is abandoned and incompatible
2
Always disable /v3/api-docs and /swagger-ui in production
add a security test to prevent accidental re-enablement
3
Document every HTTP response status code with @ApiResponse including a realistic example error body
4
Define JWT Bearer security in the global OpenAPI bean and override with security = {} on public endpoints
5
Generate and commit the OpenAPI spec in CI; use openapi-diff to catch breaking changes in pull requests
Common mistakes to avoid
6 patterns
×
Using springfox with Spring Boot 3.x
Symptom
Failed to start ApplicationContext, NullPointerException in springfox auto-configuration
Fix
Replace springfox with springdoc-openapi-starter-webmvc-ui 2.x. The migration is mostly removing Docket beans and @EnableSwagger2 — most annotations are compatible or have direct equivalents.
×
Leaving Swagger UI enabled in production
Symptom
Full API surface exposed to the internet; discovered in a security audit or by an attacker
Fix
Set springdoc.swagger-ui.enabled=false and springdoc.api-docs.enabled=false in production configuration. Add a security test asserting /v3/api-docs returns 403 in prod profile.
×
Not documenting error responses
Symptom
Partners treat 422 as a bug and file support tickets; frontends crash on unexpected error shapes
Fix
Add @ApiResponse for every possible status code. Document the error response schema with @Content and a realistic @ExampleObject showing the error body.
×
Applying global security to public endpoints
Symptom
Login and signup endpoints show a padlock in Swagger UI; developers get confused about which endpoints require auth
Fix
On public endpoints, set @Operation(security = {}) to override the global security requirement.
×
Using @Hidden on all sensitive data but not restricting at the security layer
Symptom
Hidden endpoints are removed from Swagger UI but still accessible — @Hidden is documentation-only
Fix
Pair @Hidden with Spring Security URL authorization rules. @Hidden does not add any access control.
×
Not providing realistic example values in @Schema
Symptom
Swagger UI shows minimal or auto-generated examples; developers send malformed requests because they don't know the expected format
Fix
Add example = '...' to every @Schema field annotation with a realistic value that would pass validation.
INTERVIEW PREP · PRACTICE MODE
Interview Questions on This Topic
Q01JUNIOR
What is the difference between springfox and springdoc-openapi, and whic...
Q02JUNIOR
How do you add a JWT Bearer authentication scheme to your OpenAPI spec i...
Q03JUNIOR
How do you exclude a controller endpoint from the generated OpenAPI spec...
Q04SENIOR
What is the difference between @Schema(requiredMode = REQUIRED) and @Not...
Q05SENIOR
How do you split a large API into multiple Swagger UI groups in springdo...
Q06SENIOR
How do you ensure your OpenAPI spec stays in sync with your code in a CI...
Q07SENIOR
How would you aggregate OpenAPI specs from multiple microservices in a s...
Q08SENIOR
How would you implement API versioning and reflect it accurately in the ...
Q01 of 08JUNIOR
What is the difference between springfox and springdoc-openapi, and which should you use for Spring Boot 3?
ANSWER
springfox is the legacy Swagger integration library that generates OpenAPI 2 specs and was never updated for Spring Boot 3 / Jakarta EE. springdoc-openapi generates OpenAPI 3 specs, supports Spring Boot 3, Jakarta EE, WebFlux, and is actively maintained. For any new Spring Boot 3 project, use springdoc-openapi-starter-webmvc-ui 2.x.
Q02 of 08JUNIOR
How do you add a JWT Bearer authentication scheme to your OpenAPI spec in Spring Boot?
ANSWER
Define a SecurityScheme in a @Bean OpenAPI config with type HTTP, scheme 'bearer', and bearerFormat 'JWT'. Apply it globally with openAPI.addSecurityItem() or per-endpoint with @SecurityRequirement(name = 'bearerAuth'). The name must match between the scheme definition and the SecurityRequirement annotation.
Q03 of 08JUNIOR
How do you exclude a controller endpoint from the generated OpenAPI spec?
ANSWER
Annotate the method or class with @Hidden from the io.swagger.v3.oas.annotations package. This removes it from all groups and the default spec. Remember that @Hidden is documentation-only and does not enforce access control — always pair it with Spring Security authorization rules.
Q04 of 08SENIOR
What is the difference between @Schema(requiredMode = REQUIRED) and @NotNull?
ANSWER
@Schema(requiredMode = REQUIRED) marks a field as required in the OpenAPI spec documentation — it affects what Swagger UI shows and what generated client code expects. @NotNull is a Bean Validation annotation that enforces the constraint at runtime. Both should be used together: one documents, one enforces.
Q05 of 08SENIOR
How do you split a large API into multiple Swagger UI groups in springdoc?
ANSWER
Define multiple GroupedOpenApi @Beans with different group names and pathsToMatch, pathsToExclude, or packagesToScan configurations. Each group gets its own /v3/api-docs/{group-name} endpoint and appears as a separate entry in the Swagger UI dropdown. Use addOpenApiCustomizer to give each group its own title and metadata.
Q06 of 08SENIOR
How do you ensure your OpenAPI spec stays in sync with your code in a CI/CD pipeline?
ANSWER
Use the springdoc-openapi-maven-plugin to generate the spec at build time, commit the generated openapi.yaml to the repository, and run openapi-diff in CI to compare the newly generated spec against the committed version. Breaking changes (removed fields, changed types) fail the build. This prevents spec drift and enables automated SDK regeneration.
Q07 of 08SENIOR
How would you aggregate OpenAPI specs from multiple microservices in a single Swagger UI?
ANSWER
Configure Swagger UI on the API gateway with the springdoc urls configuration pointing to each service's /v3/api-docs endpoint. The Swagger UI dropdown lets developers switch between services. Alternatively, use Spring Cloud Gateway's built-in Swagger aggregation or a dedicated API documentation portal like Backstage or Redoc.
Q08 of 08SENIOR
How would you implement API versioning and reflect it accurately in the OpenAPI spec?
ANSWER
Use URL path versioning (/api/v1/, /api/v2/) and define a GroupedOpenApi per version. This gives each version its own spec, its own Swagger UI tab, and its own schema definitions. Annotate v1 endpoints with @Operation(deprecated = true) when v2 supersedes them, and document the migration path in the description. Commit both specs to CI and compare them separately with openapi-diff.
01
What is the difference between springfox and springdoc-openapi, and which should you use for Spring Boot 3?
JUNIOR
02
How do you add a JWT Bearer authentication scheme to your OpenAPI spec in Spring Boot?
JUNIOR
03
How do you exclude a controller endpoint from the generated OpenAPI spec?
JUNIOR
04
What is the difference between @Schema(requiredMode = REQUIRED) and @NotNull?
SENIOR
05
How do you split a large API into multiple Swagger UI groups in springdoc?
SENIOR
06
How do you ensure your OpenAPI spec stays in sync with your code in a CI/CD pipeline?
SENIOR
07
How would you aggregate OpenAPI specs from multiple microservices in a single Swagger UI?
SENIOR
08
How would you implement API versioning and reflect it accurately in the OpenAPI spec?
SENIOR
FAQ · 6 QUESTIONS
Frequently Asked Questions
01
Does springdoc-openapi work with Spring WebFlux?
Yes. Use springdoc-openapi-starter-webflux-ui for reactive applications. For functional routing endpoints, annotate with @RouterOperations and @RouterOperation to provide operation metadata that springdoc cannot auto-discover from router functions.
Was this helpful?
02
How do I access Swagger UI behind Spring Security?
Permit the Swagger UI and API docs paths in your SecurityFilterChain: .requestMatchers('/swagger-ui/', '/v3/api-docs/').permitAll(). For production, require authentication instead: .requestMatchers('/swagger-ui/**').hasRole('DEVELOPER').
Was this helpful?
03
Can I generate OpenAPI spec without starting the full application?
Yes, using the springdoc-openapi-maven-plugin or springdoc-openapi-gradle-plugin. The plugin starts a Spring test context, generates the spec by calling /v3/api-docs, and writes it to a file. This is the recommended approach for CI spec generation.
Was this helpful?
04
How do I document pagination parameters for Spring Data Pageable?
springdoc auto-generates page, size, and sort parameters for Pageable arguments by default. Customize them with @ParameterObject on the Pageable parameter: @ParameterObject Pageable pageable. This renders individual fields instead of a single opaque Pageable object in Swagger UI.
Was this helpful?
05
How do I add custom extensions (x-*) to my OpenAPI spec?
Use addExtension() on Operation, Schema, or other spec objects in an OpenApiCustomizer or an OperationCustomizer bean. For example, add x-rate-limit to every operation, or x-internal:true to mark internal endpoints for API gateway policies.
Was this helpful?
06
Why are my @Schema annotations not showing up in Swagger UI?
Most commonly because the DTO class is not reachable from any controller's method signature. springdoc only includes schemas that are transitively reachable. Also check that you're importing @Schema from io.swagger.v3.oas.annotations.media.Schema, not from springfox.