1. Overview
In this tutorial, we'll discuss the main differences between Swagger’s @ApiOperation and @ApiResponse annotations.
2. Descriptive Documentation With Swagger
When we create a REST API, it's important to create its proper specification as well. Additionally, such a specification should be readable, understandable, and provide all essential information.
Moreover, the documentation should have a description of every change made on the API. It'd be exhausting and, more importantly, time-consuming to create REST API documentation manually. Fortunately, tools like Swagger can help us with this process.
Swagger represents a set of open-source tools built around OpenAPI Specification. It can help us design, build, document, and consume REST APIs.
The Swagger Specification is a standard for documenting REST APIs. Using Swagger Specification we can describe our entire API, such as exposed endpoints, operations, parameters, authentication methods, and so on.
Swagger provides various annotations that can help us document REST API. Moreover, it provides the @ApiOperation and @ApiResponse annotations to document responses for our REST API. In the remainder of this tutorial, we'll use the below controller class and see how to use these annotations:
@RestController
@RequestMapping("/customers")
class CustomerController {
private final CustomerService customerService;
public CustomerController(CustomerService customerService) {
this.customerService = customerService;
}
@GetMapping("/{id}")
public ResponseEntity<CustomerResponse> getCustomer(@PathVariable("id") Long id) {
return ResponseEntity.ok(customerService.getById(id));
}
}
3. @ApiOperation
The @ApiOperation annotation is used to describe a single operation. An operation is a unique combination of a path and an HTTP method.
Additionally, using @ApiOperation, we can describe the result of a successful REST API call. In other words, we can use this annotation to specify the general return type.
Let's add the annotation to our method:
@ApiOperation(value = "Gets customer by ID",
response = CustomerResponse.class,
notes = "Customer must exist")
@GetMapping("/{id}")
public ResponseEntity<CustomerResponse> getCustomer(@PathVariable("id") Long id) {
return ResponseEntity.ok(customerService.getById(id));
}
Next, we'll go through some of the most used properties within @ApiOperation.
3.1. The value Property
The required value property contains the operation's summary field. Simply put, it provides a short description of the operation. However, we should keep this parameter shorter than 120 characters.
Here's how we define the value property inside the @ApiOperation annotation:
@ApiOperation(value = "Gets customer by ID")
3.2. The notes Property
Using notes, we can provide more details about the operation. For instance, we can place a text describing the endpoint's restrictions:
@ApiOperation(value = "Gets customer by ID", notes = "Customer must exist")
3.3. The response Property
The response property contains the response type of the operation. In addition, setting this property would override any automatically-derived data type. The response property defined inside the @ApiOperation annotation should contain the general response type.
Let’s create the class that will represent the successful response our method returns:
class CustomerResponse {
private Long id;
private String firstName;
private String lastName;
// getters and setters
}
Next, let's add the response property to our annotation:
@ApiOperation(value = "Gets customer by ID",
response = CustomerResponse.class,
notes = "Customer must exist")
@GetMapping("/{id}")
public ResponseEntity<CustomerResponse> getCustomer(@PathVariable("id") Long id) {
return ResponseEntity.ok(customerService.getById(id));
}
3.4. The code Property
The code property represents the HTTP status of the response code. There are several definitions of HTTP Status Codes. One of them should be used. If we don't provide it, the default value will be 200.
4. @ApiResponse
It's a common practice to return errors using HTTP status codes. We can use the @ApiResponse annotation to describe the concrete possible response of an operation.
While the @ApiOperation annotation describes an operation and a general return type, the @ApiResponse annotation describes the rest of the possible return codes.
Furthermore, the annotation can be applied at the method level as well as at the class level. Moreover, annotation put on the class level will be parsed only if an @ApiResponse annotation with the same code is not already defined on the method level. In other words, the method annotations have precedence over class annotations.
We should use the @ApiResponse annotations within the @ApiResponses annotation, whether we have one or multiple responses. If we use this annotation directly, it will not be parsed by Swagger.
Let's define the @ApiResponses and @ApiResponse annotations on our method:
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Invalid ID supplied"),
@ApiResponse(code = 404, message = "Customer not found")})
@GetMapping("/{id}")
public ResponseEntity<CustomerResponse> getCustomer(@PathVariable("id") Long id) {
return ResponseEntity.ok(customerService.getById(id));
}
We can use the annotation to specify the success response as well:
@ApiOperation(value = "Gets customer by ID", notes = "Customer must exist")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = CustomerResponse.class),
@ApiResponse(code = 400, message = "Invalid ID supplied"),
@ApiResponse(code = 404, message = "Customer not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ErrorResponse.class)})
@GetMapping("/{id}")
public ResponseEntity<CustomerResponse> getCustomer(@PathVariable("id") Long id) {
return ResponseEntity.ok(customerService.getById(id));
}
If we specify the successful response using the @ApiResponse annotation, there's no need to define it inside the @ApiOperation annotation.
Now, let's go through some of the properties used within @ApiResponse.
4.1. The code and message Properties
Both code and message properties are required parameters in the @ApiResponse annotation.
As with the code property inside the @ApiOperation annotation, it should contain the HTTP status code of the response. It's important to mention we cannot define more than one @ApiResponse with the same code property.
The message property usually contains a human-readable message that goes along with the response:
@ApiResponse(code = 400, message = "Invalid ID supplied")
4.2. The response Property
Sometimes, an endpoint uses different response types. For example, we can have one type for success response and another for error response. We can describe them using the optional response property by associating a response class with a response code.
Firstly, let's define a class that will be returned in case of an internal server error:
class ErrorResponse {
private String error;
private String message;
// getters and setters
}
Secondly, let's add a new @ApiResponse for internal server errors:
@ApiResponses(value = {
@ApiResponse(code = 400, message = "Invalid ID supplied"),
@ApiResponse(code = 404, message = "Customer not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ErrorResponse.class)})
@GetMapping("/{id}")
public ResponseEntity<CustomerResponse> getCustomer(@PathVariable("id") Long id) {
return ResponseEntity.ok(customerService.getById(id));
}
5. Differences Between @ApiOperation and @ApiResponse
To sum up, the following table shows the main differences between the @ApiOperation and @ApiResponse annotations:
@ApiOperation |
@ApiResponse |
Used for describing an operation |
Used for describing the possible response of an operation |
Used for a successful response |
Used for successful and error responses |
Can be defined only on the method level |
Can be defined on a method or class level |
Can be used directly |
Can be used only within the @ApiResponses annotation |
The default code property value is 200 |
Does not have a default code property value |
6. Conclusion
In this article, we learnt the differences between the @ApiOperation and @ApiResponse annotations.
As always, the source code for the examples is available over on GitHub.
Course – LS (cat=Spring)
Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:
>> THE COURSE
res – REST (eBook) (cat=REST)