Description
Describe the bug
When I define a custom OpenApiCustomizer
to customize the OpenAPI metadata (info
, servers
) using external properties, the values set in the customizer are not reflected in the final OpenAPI output.
I confirmed that the OpenApiCustomizer
is invoked, but its settings appear to be overwritten — possibly by OperationIdCustomizer
or another internal component.
To Reproduce
-
Spring Boot version:
3.5.2
-
springdoc-openapi version:
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.9'
-
application.yml
springdoc: custom: title: joy admin api version: v1.0.1 servers: - url: http://localhost:8081 description: local
-
Spring Configuration:
@Configuration @EnableConfigurationProperties(SpringDocProperties.class) @RequiredArgsConstructor public class SpringDocConfig { private final SpringDocProperties springDocProperties; @Bean OpenApiCustomizer commonOpenApiCustomizer() { return openApi -> openApi.servers(servers()) .info(info()); } private List<Server> servers() { return springDocProperties.getServers() .stream() .map(s -> new Server().url(s.getUrl()).description(s.getDescription())) .toList(); } private Info info() { return new Info() .title(springDocProperties.getTitle()) .version(springDocProperties.getVersion()); } }
-
Property Binding Class:
@Configuration @ConfigurationProperties("springdoc.custom") @Data public class SpringDocProperties { private String title = "API"; private String version = "v0.0.1"; private List<ServerInfo> servers = List.of(); @Data public static class ServerInfo { private String url; private String description; } }
-
Actual Behavior:
When accessing
http://localhost:8081/v3/api-docs/springdocDefault
, the OpenAPI spec still shows:{ "info": { "title": "OpenAPI definition", "version": "v0" } }
Even though
OpenApiCustomizer
should set it to:{ "title": "joy admin api", "version": "v1.0.1" }
-
Expected Behavior:
The customizer should override the
OpenAPI.info()
andOpenAPI.servers()
sections. However, the current behavior suggests that these values are reset later in the pipeline. -
Workaround:
If I define a full
@Bean OpenAPI customOpenAPI()
, it works as expected:@Bean public OpenAPI customOpenAPI() { return new OpenAPI() .info(new Info().title(springDocProperties.getTitle()).version(springDocProperties.getVersion())); }
But this defeats the purpose of using
OpenApiCustomizer
.
Screenshots
Not applicable — reproducible via JSON inspection at /v3/api-docs
.
Additional context
This might be related to OperationIdCustomizer
or another internal component that applies a new OpenAPI.info()
object, thereby discarding the result from the customizer.
Would be helpful to clarify precedence between customizers and internal configurations — or provide a way to prevent overwriting custom OpenApiCustomizer
behavior.