Reputation: 447
I am currently migrating from springfox to springdoc-openapi-ui and have run into some issues that the migration documentation does not touch on.
I am getting the error Cannot resolve method 'response'
at response = Example.class
and response = ErrorResponse.class
below.
I've tried using responses
instead but had no luck.
With springfox, my code looked like this:
@ApiOperation(
value = "sample summary",
response = Example.class,
notes = "sample description")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful"),
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
@ApiResponse(code = 401, message = "Not Authorized", response = ErrorResponse.class),
@ApiResponse(code = 403, message = "Forbidden", response = ErrorResponse.class),
@ApiResponse(code = 404, message = "Not Found", response = ErrorResponse.class)})
@PostMapping(value = {"/sampleEndpoint"}, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
after migrating to springdoc, here's where it stands:
@Operation(
summary = "sample summary",
response = Example.class,
description = "sample description")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successful"),
@ApiResponse(responseCode = "400", description = "Bad Request", response = ErrorResponse.class),
@ApiResponse(responseCode = "401", description = "Not Authorized", response = ErrorResponse.class),
@ApiResponse(responseCode = "403", description = "Forbidden", response = ErrorResponse.class),
@ApiResponse(responseCode = "404", description = "Not Found", response = ErrorResponse.class)})
@PostMapping(value = {"/sampleEndpoint"}, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
Upvotes: 3
Views: 2673
Reputation: 2595
You can use
content = @Content(mediaType =...,schema = @Schema(implementation=...))
You didn't show the rest of your code, but I'm assuming you're returning your ErrorResponse class as json in the 4xx responses?
If so, I think the spring-doc definition would look something like this:
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ErrorResponse.class)))
I couldn't find a direct example of this on the base spring-doc page, but how to hide a schema has something similar: https://springdoc.org/#how-can-i-hide-schema-of-the-the-response
Edit for your comments:
Since you specified the produces type in the PostMapping spring-doc will infer this for all responses by default, so there's no need to specify that in the @Content annotation.
It's not entirely clear to me what your method signature looks like:
ResponseEntity<String>
and mapping the json in the error response yourself?ResponseEntity<ErrorResponse>
and then returning an empty body on 200?spring-doc will automatically attempt to infer the response schema based on the return type, so if you're doing the second one, you won't need to specify the @Content type at all (except on the 200 response where you're returning an empty body, where you'll want to specify just by using an empty @Content
annotation to omit the schema).
If you'd like the schema (with examples) to show up in your spring-doc interface you're going to want to include the schema = @Schema(implementation = ...)
portion.
Here's a further example of what I think you might be trying to achieve:
@Operation(summary = "sample summary",
description = "sample description")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successful", content = @Content),
@ApiResponse(responseCode = "400", description = "Bad Request", content =
@Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "401", description = "Not Authorized", content =
@Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "403", description = "Forbidden", content =
@Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "404", description = "Not Found", content =
@Content(schema = @Schema(implementation = ErrorResponse.class)))
})
@PostMapping(value = {"/sampleEndpoint"}, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> postSampleEndpoint() {
// just a fake response here
ErrorResponse exampleErrorResponse = new ErrorResponse("fakeErrorDescription", "fakeSuggestion");
ObjectMapper mapper = new ObjectMapper();
String jsonErrorResult;
try {
jsonErrorResult = mapper.writeValueAsString(exampleErrorResponse);
} catch (JsonProcessingException e) {
// fill the json error manually with something else if mapping fails
throw new RuntimeException(e);
}
return new ResponseEntity<>(jsonErrorResult, HttpStatus.BAD_REQUEST);
}
@Operation(summary = "sample summary",
description = "sample description")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successful", content = @Content),
@ApiResponse(responseCode = "400", description = "Bad Request"),
@ApiResponse(responseCode = "401", description = "Not Authorized"),
@ApiResponse(responseCode = "403", description = "Forbidden"),
@ApiResponse(responseCode = "404", description = "Not Found")
})
@PostMapping(value = {"/sampleEndpoint"}, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ErrorResponse> postSampleEndpoint() {
// just a fake response here
ErrorResponse exampleErrorResponse = new ErrorResponse("fakeErrorDescription", "fakeSuggestion");
return new ResponseEntity<>(exampleErrorResponse, HttpStatus.BAD_REQUEST);
}
Then in the ErrorResponse
model class you can use the @Schema
annotation to provide examples:
ErrorResponse.java:
public class ErrorResponse {
@JsonProperty("error_description")
@Schema(example = "Example Error Description")
private String errorDescription;
@Schema(example = "Example Suggestion")
private String suggestion;
public ErrorResponse(String errorDescription, String suggestion) {
this.errorDescription = errorDescription;
this.suggestion = suggestion;
}
public String getErrorDescription() {
return errorDescription;
}
public void setErrorDescription(String errorDescription) {
this.errorDescription = errorDescription;
}
public String getSuggestion() {
return suggestion;
}
public void setSuggestion(String suggestion) {
this.suggestion = suggestion;
}
}
Which generates a swagger doc UI like this:
Upvotes: 5