6

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:

  • Spring Boot => 2.2.4.Release
  • springdoc-openapi-ui => 1.3.0
  • springdoc-openapi-security => 1.3.0
pedro_silva
  • 143
  • 2
  • 6

1 Answers1

14

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.

TomStroemer
  • 1,390
  • 8
  • 28
  • 3
    While creating openApi bean, paths will be null. What is the hook you are using for customizing paths on openApi object i.e., to execute openApi.getPaths().values().forEach(pathItem -> {}), – Pavan Kumar Mar 04 '21 at 15:58
  • This is an awesome post. Very helpful.Thank you! – Jonathan Locke Sep 18 '21 at 20:02
  • Is there something like ModelConverters for reading the Parameters model from a method? – Jonathan Locke Sep 19 '21 at 02:22
  • 1
    Better than manually registering all classes, do this (Kotlin): ModelConverters.getInstance().readAllAsResolvedSchema(RootErrorClass::class.java).referencedSchemas.forEach { (k, v) -> openApi.components.addSchemas(k, v) } This will automatically resolve all unknown complex types. – Michael Böckling Apr 27 '22 at 15:42
  • @PavanKumar use a `OpenApiCustomizer` instead – Dimio Nov 16 '22 at 11:48