Introduction:
Swagger 3, also known as OpenAPI 3, is a specification for documenting and defining RESTful APIs. It is the third major version of the Swagger specification, which was originally developed by SmartBear Software and later contributed to the OpenAPI Initiative, a consortium of companies and individuals that work together to standardize and evolve the Swagger/OpenAPI specification.
OpenAPI Specification sets forth a set of guidelines for API development and documentation, encompassing versioning, schema, document structure, and other critical elements, which contributes to creating reliable and consistent APIs.
Swagger provides a range of tools (Swagger Editor, Swagger UI, Swagger Codegen…) to support the development, testing, and documentation of these APIs. So we can think about Swagger 3 as OpenAPI 3 specification implementation.
Swagger 3 vs OpenAPI 3?
- All Swagger tools, which are supported by SmartBear Software, utilize OpenAPI Specification.
- But not all OpenAPI tools are Swagger tools. There are many open source and pro tools, which are not related to Swagger, support the OpenAPI 3 Specification.
Swagger 3 annotations
Swagger 3 annotations are already included in springdoc-openapi-ui dependency for Spring Boot 2, or springdoc-openapi-starter-webmvc-ui for Spring Boot 3 with io.swagger.v3.oas.annotations package.
Here are some useful annotations:
- @Tag
- @Operation
- @Parameters and @Parameter
- @Schema
- @Hidden or @Parameter(hidden = true) or @Operation(hidden = true)
- @ApiResponses and @ApiResponse
Swagger 2 to Swagger 3 annotations
- @Api → @Tag
- @ApiIgnore → @Parameter(hidden = true) or @Operation(hidden = true) or @Hidden
- @ApiImplicitParam → @Parameter
- @ApiImplicitParams → @Parameters
- @ApiModel → @Schema
- @ApiModelProperty(hidden = true) → @Schema(accessMode = READ_ONLY)
- @ApiModelProperty → @Schema
- @ApiOperation(value = "foo", notes = "bar") → @Operation(summary = "foo", description = "bar")
- @ApiParam → @Parameter
- @ApiResponse(code = 404, message = "foo") → @ApiResponse(responseCode = "404", description = "foo")
Add Swagger 3 into Spring Boot
<dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.0.3</version></dependency>
Or Gradle project with build.gradle file:
implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.0.3'
<dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-ui</artifactId><version>1.6.15</version></dependency>
Or Gradle project with build.gradle file:
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.15'
Swagger 3 annotations example
Rest API
Assume that we have Spring Boot Application that exposes Rest APIs for a Tutorial application in that:
- Each Tutorial has id, title, description, published status.
- Apis help to create, retrieve, update, delete Tutorials.
- Apis also support custom finder methods such as find by published status or by title.
Methods Urls Actions
POST /api/tutorials create new Tutorial
GET /api/tutorials retrieve all Tutorials
GET /api/tutorials/:id retrieve a Tutorial by :id
PUT /api/tutorials/:id update a Tutorial by :id
DELETE /api/tutorials/:id delete a Tutorial by :id
DELETE /api/tutorials delete all Tutorials
GET /api/tutorials/published find all published Tutorials
GET /api/tutorials?title=[keyword] find all Tutorials which title contains keyword
Let’s use Swagger 3 annotations in our Spring Boot app
Swagger 3 @Tag annotation
@Tag(name = "Tutorial", description = "Tutorial management APIs")@RestController@RequestMapping("/api")public class TutorialController {@PostMapping("/tutorials")public ResponseEntity<Tutorial> createTutorial(@RequestBody Tutorial tutorial) {}@GetMapping("/tutorials")public ResponseEntity<List<Tutorial>> getAllTutorials(@RequestParam(required = false) String title) {}@GetMapping("/tutorials/{id}")public ResponseEntity<Tutorial> getTutorialById(@PathVariable("id") long id) {}@PutMapping("/tutorials/{id}")public ResponseEntity<Tutorial> updateTutorial(@PathVariable("id") long id, @RequestBody Tutorial tutorial) {}@DeleteMapping("/tutorials/{id}")public ResponseEntity<HttpStatus> deleteTutorial(@PathVariable("id") long id) {}@DeleteMapping("/tutorials")public ResponseEntity<HttpStatus> deleteAllTutorials() {}@GetMapping("/tutorials/published")public ResponseEntity<List<Tutorial>> findByPublished() {}}
When the Swagger documentation is generated, the @Tag annotation will group all of the operations that belong to the “Tutorial” tag together in the documentation. This makes it easy for users to find all of the operations that are related to tutorials.
The @Tag annotation can be added to a method inside a Controller to provide a name and description for the tag. For example:
public class TutorialController {
@Tag(name = "tutorials", description = "Tutorial APIs")@PostMapping("/tutorials")
public ResponseEntity<Tutorial> createTutorial(@RequestBody Tutorial tutorial) {
}
}
Swagger 3 @Operation annotation
public class TutorialController {@Operation(summary = "Retrieve a Tutorial by Id",description = "Get a Tutorial object by specifying its id. The response is Tutorial object with id, title, description and published status.",tags = { "tutorials", "get" })@GetMapping("/tutorials/{id}")public ResponseEntity<Tutorial> getTutorialById(@PathVariable("id") long id) {}}
In this example, the @Operation annotation provides a summary, description and set tags for the getTutorialById method operation.
Swagger 3 @ApiResponses and @ApiResponse annotation
In Swagger 3, the @ApiResponses annotation can be added to an API operation method to provide a list of possible responses for that operation. Each response is specified using an @ApiResponse annotation.
The @ApiResponse annotation specifies the HTTP status code, description, and content of a response. The content is described using the @Content annotation, which includes the media type and schema of the response body.
public class TutorialController {
@ApiResponses({
@ApiResponse(responseCode = "200", content = { @Content(schema = @Schema(implementation = Tutorial.class), mediaType = "application/json") }),
@ApiResponse(responseCode = "404", description = "The Tutorial with given Id was not found.", content = { @Content(schema = @Schema()) })
})
@GetMapping("/tutorials/{id}")
public ResponseEntity<Tutorial> getTutorialById(@PathVariable("id") long id) {
}
}
In this example, the @ApiResponse annotation is used to define two possible responses for the getTutorialById method. The first response (responseCode = "200") indicates a successful response with a JSON representation of the Tutorial object in the response body. The second response (responseCode = "404") indicates that the requested Tutorial Id was not found.
Swagger 3 @Parameter annotation
The @Parameter annotation in Swagger 3 is used to describe a parameter for an operation in an OpenAPI / Swagger document. For example:
public class TutorialController {
@GetMapping("/tutorials")
public ResponseEntity<Map<String, Object>> getAllTutorials(
@Parameter(description = "Search Tutorials by title") @RequestParam(required = false) String title,
@Parameter(description = "Page number, starting from 0", required = true) @RequestParam(defaultValue = "0") int page,
@Parameter(description = "Number of items per page", required = true) @RequestParam(defaultValue = "3") int size) {
}
}
In the example, the @Parameter annotation describes each of the parameters (title, page, and size) of the getAllTutorials method. The description attribute provides a brief description of each parameter, and the required attribute is set to true to indicate that the parameter is mandatory.
Note that the @Parameter annotation can be used in conjunction with other annotations, such as @RequestParam, @PathVariable, or @RequestBody, depending on the type of parameter being described.
Here is the result:
Or you can use @Parameters annotation to define multiple input parameters for an operation.
public class TutorialController {
@Parameters({
@Parameter(name = "title", description = "Search Tutorials by title"),
@Parameter(name = "page", description = "Page number, starting from 0", required = true),
@Parameter(name = "size", description = "Number of items per page", required = true)
})
@GetMapping("/tutorials")
public ResponseEntity<Map<String, Object>> getAllTutorials(
@RequestParam(required = false) String title,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "3") int size) {
return null;
}
}
Swagger 3 @Schema annotation
In Swagger 3, the @Schema annotation is used in to provide additional information about the schema of a model or parameter in your API.
Let’s use @Schema annotation to define a schema for a Tutorial object.
@Schema(description = "Tutorial Model Information")
public class Tutorial {
@Schema(accessMode = Schema.AccessMode.READ_ONLY, description = "Tutorial Id", example = "123")
private long id = 0;
@Schema(description = "Tutorial's title", example = "Swagger Tutorial")
private String title;
@Schema(description = "Tutorial's description", example = "Document REST API with Swagger 3")
private String description;
@Schema(description = "Tutorial's status (published or not)", example = "true")
private boolean published;
public Tutorial() {
}
// getters and setters
}
In the example above, the @Schema annotation provides additional information about the Tutorial class and its fields. The description attribute provides a brief description of what each field represents, while the example attribute provides a sample value for each field.
We use accessMode = Schema.AccessMode.READ_ONLY in the id property. This will mark the id property as readOnly: true in the generated OpenAPI definition.
The Schema with its example value is changed now.
Conclusion
Thank you
No comments:
Post a Comment