Spring Boot REST API Documentation with Swagger

In this tutorial, we will learn how to add step-by-step Swagger to the existing Spring boot application and generate Swagger API documentation.

In this tutorial, we'll look at Swagger 2 for a Spring Boot REST web service, using the Springfox implementation of the Swagger 2 specification

Step 1: Adding the Maven Dependency to Spring Boot Project

Let's open pom.xml and below single maven springfox-boot-starter dependency:
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>
 After adding the springfox-boot-starter dependency, spring boot will auto-configure Swagger in Spring boot so we don't need to manually add annotations to enable Swagger.

Access Swagger documentation JSON API

Here is the URL format:

http://localhost:8080/your-app-root/v2/api-docs

Consider we are creating blog app and to verify that Springfox is working, we can visit this URL in our browser:

http://localhost:8080/blog-app/v2/api-docs


Step 2: Integrating Swagger 2 Into the Spring Boot Project

Let's create a SwaggerConfig class and annotate with @Configuration annotation. The configuration of Swagger mainly centers around the Docket bean so let's add the below code to SwaggerConfig class:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Configuration
public class SwaggerConfiguration {

    private ApiInfo apiInfo() {
        return new ApiInfo("Blog REST APIs",
                "REST APIs for Blog Application",
                "1.0",
                "Terms of service",
                new Contact("Ramesh Fadatare", "www.javaguides.net", "ramesh@gmail.com"),
                "License of API",
                "API license URL",
                Collections.emptyList());
    }

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }
}
After defining the Docket bean, it's select() method returns an instance of ApiSelectorBuilder, which provides a way to control the endpoints exposed by Swagger.

We can configure predicates for selecting RequestHandlers with the help of RequestHandlerSelectors and PathSelectors. Using any() for both will make documentation for our entire API available through Swagger.

Step 3: Accessing Swagger UI

Swagger UI is a built-in solution that makes user interaction with the Swagger-generated API documentation much easier.

Let's say we are creating a blog application so in our case, the exact URL will be:


The result should look something like this:



Customizing Swagger REST Documentation with Annotations

In order to customize the Swagger documentation, swagger-core offers a set of annotations to declare and manipulate the output. 

Swagger-core Annotations:

NameDescription
@ApiMarks a class as a Swagger resource.
@ApiModelProvides additional information about Swagger models.
@ApiModelPropertyAdds and manipulates data of a model property.
@ApiOperationDescribes an operation or typically an HTTP method against a specific path.
@ApiParamAdds additional meta-data for operation parameters.
@ApiResponseDescribes a possible response of an operation.
@ApiResponsesA wrapper to allow a list of multiple ApiResponse objects.
You can find more details about swagger annotations on https://github.com/swagger-api/swagger-core/wiki/annotations
Below code snippet shows how to use @Api and @ApiOperation annotations to provide additional information to REST APIs:
@Api(value = "CRUD Rest APIs for Post resources")
@RestController
@RequestMapping()
public class PostController {

    private PostService postService;

    public PostController(PostService postService) {
        this.postService = postService;
    }

    @ApiOperation(value = "Create Post REST API")
    @PostMapping("/api/v1/posts")
    public ResponseEntity<PostDto> createPost(@Valid @RequestBody PostDto postDto){
        return new ResponseEntity<>(postService.createPost(postDto), HttpStatus.CREATED);
    }

    @ApiOperation(value = "Get All Posts REST API")
    @GetMapping("/api/v1/posts")
    public PostResponse getAllPosts(
            @RequestParam(value = "pageNo", defaultValue = AppConstants.DEFAULT_PAGE_NUMBER, required = false) int pageNo,
            @RequestParam(value = "pageSize", defaultValue = AppConstants.DEFAULT_PAGE_SIZE, required = false) int pageSize,
            @RequestParam(value = "sortBy", defaultValue = AppConstants.DEFAULT_SORT_BY, required = false) String sortBy,
            @RequestParam(value = "sortDir", defaultValue = AppConstants.DEFAULT_SORT_DIRECTION, required = false) String sortDir
    ){
        return postService.getAllPosts(pageNo, pageSize, sortBy, sortDir);
    }

    @ApiOperation(value = "Get Post By Id REST API")
    @GetMapping(value = "/api/v1/posts/{id}")
    public ResponseEntity<PostDto> getPostByIdV1(@PathVariable(name = "id") long id){
        return ResponseEntity.ok(postService.getPostById(id));
    }

    @ApiOperation(value = "Update Post By Id REST API")
    @PutMapping("/api/v1/posts/{id}")
    public ResponseEntity<PostDto> updatePost(@Valid @RequestBody PostDto postDto, @PathVariable(name = "id") long id){

       PostDto postResponse = postService.updatePost(postDto, id);

       return new ResponseEntity<>(postResponse, HttpStatus.OK);
    }

    @ApiOperation(value = "Delete Post By Id REST API")
    @DeleteMapping("/api/v1/posts/{id}")
    public ResponseEntity<String> deletePost(@PathVariable(name = "id") long id){

        postService.deletePostById(id);

        return new ResponseEntity<>("Post entity deleted successfully.", HttpStatus.OK);
    }
}
Below code snippet shows how to use @ApiModel and @ApiModelProperty annotations to provide additional information about Swagger models:

@ApiModel(description = "Post model information")
@Data
public class PostDto {

    @ApiModelProperty(value = "Blog post id")
    private long id;

    // title should not be null  or empty
    // title should have at least 2 characters
    @ApiModelProperty(value = "Blog post title")
    @NotEmpty
    @Size(min = 2, message = "Post title should have at least 2 characters")
    private String title;

    // post description should be not null or empty
    // post description should have at least 10 characters
    @ApiModelProperty(value = "Blog post description")
    @NotEmpty
    @Size(min = 10, message = "Post description should have at least 10 characters")
    private String description;

    // post content should not be null or empty
    @ApiModelProperty(value = "Blog post conent")
    @NotEmpty
    private String content;

    @ApiModelProperty(value = "Blog post comments")
    private Set<CommentDto> comments;
}

Complete Course and Source Code

Building Real-Time REST APIs with Spring Boot at https://courses.javaguides.net/p/building-rest-api-with-spring-boot

Comments