-
-
Notifications
You must be signed in to change notification settings - Fork 553
Description
Bug description
Originally in OpenAPIService.build(Locale locale) ObjectMapper was obtained via Json.mapper().
This behaviour was changed in SpringDoc 1.6.7 in order to resolve #1525 to new ObjectMapper(). The problem is that this way obtained instance of ObjectMapper has no longer registered JavaTimeModule, Swagger v3 DeserializationModule and mixins.
In my application I have OperationCustomizer that adds to all REST operations schema for 5xx responses that are produced by @ControllerAdvice. In 5xx response schema I'm using Instant and since JavaTimeModule is absent, attempt to serialize openAPI to JSON and deserialize it produces JsonProcessingException. This exception is then logged with WARN level and suppressed resulting in calculatedOpenAPI = null which then later in execution is causing NullPointerException (see output log below)
INFO test.TestController : Starting TestController using Java 17.0.1 on ...
INFO test.TestController : No active profile set, falling back to 1 default profile: "default"
INFO o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
INFO o.apache.catalina.core.StandardService : Starting service [Tomcat]
INFO org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.62]
INFO o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
INFO w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 622 ms
INFO o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
INFO test.TestController : Started TestController in 1.387 seconds (JVM running for 1.657)
INFO o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
INFO o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
INFO o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
WARN org.springdoc.core.OpenAPIService : Json Processing Exception occurred: Java 8 date/time type `java.time.OffsetDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: io.swagger.v3.oas.models.OpenAPI["components"]->io.swagger.v3.oas.models.Components["schemas"]->java.util.LinkedHashMap["ErrorResponse"]->io.swagger.v3.oas.models.media.Schema["properties"]->java.util.LinkedHashMap["timestamp"]->io.swagger.v3.oas.models.media.DateTimeSchema["example"])
ERROR o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException: Cannot invoke "io.swagger.v3.oas.models.OpenAPI.getInfo()" because "this.calculatedOpenAPI" is null] with root cause
java.lang.NullPointerException: Cannot invoke "io.swagger.v3.oas.models.OpenAPI.getInfo()" because "this.calculatedOpenAPI" is null
at org.springdoc.core.OpenAPIService.build(OpenAPIService.java:262) ~[springdoc-openapi-common-1.6.8.jar:1.6.8]
at org.springdoc.api.AbstractOpenApiResource.getOpenApi(AbstractOpenApiResource.java:308) ~[springdoc-openapi-common-1.6.8.jar:1.6.8]
at org.springdoc.webmvc.api.OpenApiResource.openapiJson(OpenApiResource.java:132) ~[springdoc-openapi-webmvc-core-1.6.8.jar:1.6.8]
at org.springdoc.webmvc.api.OpenApiWebMvcResource.openapiJson(OpenApiWebMvcResource.java:111) ~[springdoc-openapi-webmvc-core-1.6.8.jar:1.6.8]
...
Sample code to Reproduce
@RestController
@SpringBootApplication
public class TestController {
public static void main(String[] args) { SpringApplication.run(TestController.class, args); }
@GetMapping("/test")
public void test() {}
@Bean
public OpenAPI openAPI() { return new OpenAPI().components(new Components()); }
@Bean
public OperationCustomizer operationCustomizer(OpenAPI api) {
var errorResponseSchema = SpringDocAnnotationsUtils.extractSchema(
api.getComponents(),
ErrorResponse.class,
null,
null
);
var errorApiResponse = new ApiResponse().content(new Content().addMediaType(
APPLICATION_JSON_VALUE,
new MediaType().schema(errorResponseSchema)
));
return (Operation operation, HandlerMethod handlerMethod) -> {
operation.getResponses().addApiResponse("5xx", errorApiResponse);
return operation;
};
}
public record ErrorResponse(
@Schema(example = "2022-05-09T00:00:00.000Z") Instant timestamp,
@Schema(example = "{\"param1\":\"val1\",\"param2\":\"val2\"}") Map<String, Object> data
) {}
}Code snippet abowe works for SpringDoc 1.6.6 or older. Since SpringDoc 1.6.7 /v3/api-docs endpoint fails with HTTP 500 response due to problem described above.