springdocspringdoc-openapi-ui

Default response class in springdoc


I am trying to add a default error model to all endpoints in my API, for some error codes.

I found a partial solution by reading the following issues:

This is the bean I am creating for that customisation:

@Bean
public OpenApiCustomiser customOpenApiCustomiser() {
    return openApi -> {
        openApi.getPaths().values().forEach(pathItem -> pathItem.readOperations().forEach(operation -> {

            Schema sharedErrorSchema = ModelConverters.getInstance()
                    .read(Error.class)
                    .getOrDefault("Error", new Schema());

            MediaType sharedMediaType = new MediaType().schema(sharedErrorSchema);
            Content sharedContent = new Content()
                    .addMediaType(APPLICATION_JSON_VALUE, sharedMediaType);

            ApiResponses apiResponses = operation.getResponses();

            ApiResponse response = new ApiResponse()
                    .description("Unhandled server error")
                    .content(sharedContent);
            apiResponses.addApiResponse("500", response);
        }));
    };
}

And my Error class looks something like:

public class Error {
    private String message;
    private List<ErrorItem> errorItems;
}

The problem is that when I open one of the endpoints definition in swagger-ui, I am getting the following error:

Could not resolve reference: Could not resolve pointer: /components/schemas/ErrorItem does not exist in document

How can I define the schema for ErrorItem, making it available for swagger-ui?

I am using:


Solution

  • I had a similiar issue and resolved it today:

    First you have to add all java-types to the components:

    // add Error and ErrorItem to schema
    openApi.getComponents().getSchemas().putAll(ModelConverters.getInstance().read(Error.class));
    openApi.getComponents().getSchemas().putAll(ModelConverters.getInstance().read(ErrorItem.class));
    

    Then you have to create a Schema-Ref to use it in your response:

    // add default responses
    // Ref to Error-Object (added in step above)
    Schema errorResponseSchema = new Schema();
    errorResponseSchema.setName("Error");
    errorResponseSchema.set$ref("#/components/schemas/Error");
    

    Now you can use this ref. In this example i use Error only for BadRequest, all other default responses don't use a schema. Change it as you need it :-)

    openApi.getPaths().values().forEach(pathItem -> pathItem.readOperations().forEach(operation -> {
      ApiResponses apiResponses = operation.getResponses();
      apiResponses.addApiResponse("400", createApiResponse("BadRequest", errorResponseSchema));
      apiResponses.addApiResponse("403", createApiResponse("Forbidden", null));
      apiResponses.addApiResponse("404", createApiResponse("Not Found", null));
      apiResponses.addApiResponse("500", createApiResponse("Server Error", null));
    }));
    

    Where createApiResponse is just a simple private function:

    private ApiResponse createApiResponse(String message, Schema schema) {
      MediaType mediaType = new MediaType();
      mediaType.schema(schema);
      return new ApiResponse().description(message)
                    .content(new Content().addMediaType(org.springframework.http.MediaType.APPLICATION_JSON_VALUE, mediaType));
    }
    

    Make sure you get the right import for your Error.class, per default it will be java.lang.Error.