Core library that generates an OpenAPI 3.0 specification from compiled Spring MVC controllers — no running server required.
This module contains all the logic: classpath scanning, annotation resolution, type hierarchy traversal, schema processing, and YAML/JSON serialisation. It is consumed by openapi-generator-maven-plugin, which provides the Maven lifecycle integration.
- Quickstart
- How It Works
- Prerequisites
- Building
- Programmatic Usage
- Architecture Overview
- Key Components
- Supported Annotations
- Schema Type Handlers
- Post-Processors
- License
This example shows how to go from a Spring MVC controller to a generated openapi.yaml in two steps.
<dependency>
<groupId>io.github.rspereiratech</groupId>
<artifactId>openapi-generator-core</artifactId>
<version>1.3.0</version>
</dependency>GeneratorConfig config = GeneratorConfig.builder()
.basePackages(List.of("com.example.controller"))
.outputFile("docs/swagger/openapi.yaml")
.title("My API")
.version("1.0.0")
.build();
new OpenApiGeneratorImpl().generate(config, Thread.currentThread().getContextClassLoader());That's it — docs/swagger/openapi.yaml is generated from your compiled controllers.
For Maven lifecycle integration (automatic generation on build), use the
openapi-generator-maven-plugininstead.
The generation pipeline executes entirely from bytecode — no Spring context is started and no HTTP server is needed.
ClasspathScanner → discovers controller classes in configured packages
OpenApiModelBuilder → initialises the OpenAPI model (info, servers, security schemes)
ControllerProcessor → for each controller: resolves base path, tags, and methods
OperationProcessor → converts each method to an OpenAPI operation
ParameterProcessor → builds path, query, header, and cookie parameters
RequestBodyProcessor → builds the request body schema reference
ResponseProcessor → builds response codes and response schema references
SchemaProcessor → resolves Java types to OpenAPI schemas (chain of responsibility)
PostProcessors → clean up and finalise the assembled model
OpenApiWriter → serialises to YAML or JSON
| Tool | Version |
|---|---|
| Java | 17+ |
| Maven | 3.9+ |
# Install the parent POM first
mvn install -f ../openapi-generator-parent/pom.xml
# Build and install this project
mvn installThe library can be used directly without the Maven plugin — useful for custom tooling, CI scripts, or testing.
GeneratorConfig config = GeneratorConfig.builder()
.basePackages(List.of("com.example.controller"))
.outputFile("docs/swagger/openapi.yaml")
.title("My API")
.version("1.0.0")
.build();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
new OpenApiGeneratorImpl().generate(config, classLoader);GeneratorConfig config = GeneratorConfig.builder()
.basePackages(List.of("com.example.controller"))
.outputFile("docs/swagger/openapi.yaml")
.title("My API")
.version("1.0.0")
.server(ServerConfig.of("https://api.example.com", "Production"))
.server(ServerConfig.of("http://localhost:8080", "Local"))
.contextPath("my-api")
.securityScheme(new SecuritySchemeConfig(
"bearerAuth", "http", "bearer", "JWT", null, null, null, null
))
.build();
new OpenApiGeneratorImpl().generate(config, classLoader);GeneratorConfig config = GeneratorConfig.builder()
.basePackages(List.of("com.example.controller"))
.outputFile("docs/swagger/openapi.yaml")
.controllerAnnotations(List.of("com.example.annotation.MyApiEndpoint"))
.title("My API")
.version("1.0.0")
.build();
new OpenApiGeneratorImpl().generate(config, classLoader);GeneratorConfig config = GeneratorConfig.builder()
.basePackages(List.of("com.example.controller"))
.outputFile("docs/swagger/openapi.json")
.outputFormat(OutputFormat.JSON)
.title("My API")
.version("1.0.0")
.build();
new OpenApiGeneratorImpl().generate(config, classLoader);Note: The
ClassLoaderpassed togenerate()must be able to load the controller classes and their dependencies. When calling from within the same application,Thread.currentThread().getContextClassLoader()is usually correct. When scanning an external project (as the Maven plugin does), aURLClassLoaderbuilt from the project's compiled classpath must be used.
See docs/Configuration.md for the full GeneratorConfig field reference.
See docs/Architecture.md for the full pipeline breakdown, component responsibilities, and design decisions.
| Component | Description |
|---|---|
OpenApiGeneratorImpl |
Main orchestrator — runs the full pipeline |
DefaultClasspathScanner |
Scans directories and JARs for controller classes |
ControllerProcessorImpl |
Walks the type hierarchy to collect tags, base paths, and methods |
OperationProcessorImpl |
Maps methods to OpenAPI operations using Spring MVC and SpringDoc annotations |
ParameterProcessorImpl |
Resolves @PathVariable, @RequestParam, @RequestHeader, @CookieValue, Pageable |
SchemaProcessorImpl |
Chain-of-responsibility for resolving Java types to OpenAPI schemas |
ValidationSchemaEnricher |
Propagates Jakarta Bean Validation constraints to OpenAPI schema properties via a chain of ConstraintHandlers |
AnnotationUtils |
Recursive meta-annotation traversal across the full type hierarchy |
@RequestMapping, @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping
@Operation, @ApiResponse, @ApiResponses, @Parameter, @RequestBody, @Tag
@PathVariable, @RequestParam, @RequestHeader, @CookieValue, @RequestBody
@ResponseStatus
@Min, @Max, @DecimalMin, @DecimalMax, @Positive, @PositiveOrZero, @Negative, @NegativeOrZero, @Size, @NotNull, @NotBlank, @NotEmpty, @Pattern, @Email
The SchemaProcessor uses a chain of responsibility. Each handler either handles the type or delegates to the next:
| Handler | Types handled |
|---|---|
VoidTypeSchemaHandler |
void, Void |
FluxTypeSchemaHandler |
Flux<T> (Project Reactor) |
PageTypeSchemaHandler |
Page<T> (Spring Data) |
PageableTypeSchemaHandler |
Pageable, PageRequest |
ModelConvertersTypeSchemaHandler |
All other types via Swagger ModelConverters |
See docs/Schema-Handlers.md for details on each handler.
After all controllers are processed, four post-processors run in sequence:
| Post-Processor | Description |
|---|---|
SchemaRegistryMergePostProcessor |
Merges component schemas collected during processing into the final model |
PruneUnreferencedSchemasPostProcessor |
Removes schemas from components/schemas that are not referenced anywhere |
SortSpecPostProcessor |
Sorts paths and response-code keys alphabetically when sortOutput is enabled |
UniqueOperationIdPostProcessor |
Disambiguates duplicate operation IDs using a numeric suffix strategy |
See docs/Post-Processors.md for details.
If you find this project useful, consider supporting its development:
Crypto donations via NOWPayments — supports BTC, ETH, USDT and many others.
This project is licensed under the MIT License — see the LICENSE file for details.