1. What is swagger?

Swagger is an Interface Description Language for describing RESTful APIs expressed using JSON. Swagger is used together with a set of open-source software tools to design, build, document, and use RESTful web services. Swagger includes automated documentation, code generation (into many programming languages), and test-case generation. For more information check out the website here. 
- Wikipedia

2. Maven Dependency

To use swagger2 in your spring boot app we need to add the following maven dependency to pom.xml.

<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger2</artifactId>
	<version>2.9.2</version>
</dependency>

3. Configuration

Now create a class for the configuring swagger2 and add @Configuration and @EnableSwagger2. This is the minimum setup you need to use swagger2 in a spring boot app.

import org.springframework.context.annotation.Configuration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

}

4. Model

We have the following user model in our spring app.

public class User {

    private int id;

    private String name;

    private int age;

    private String email;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

5. Controller

This is our rest controller for fetching and saving users from an ArrayList.

import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {

    List<User> users = new ArrayList<>();

    @GetMapping("/{id}")
    public User getUser(@PathVariable int id){
        return users.stream().filter(user -> user.getId() == id).findFirst().get();
    }

    @GetMapping("/")
    public List<User> getUsers(){
        return users;
    }

    @PostMapping("/")
    public User addUser(@RequestBody User user){
        users.add(user);
        return user;
    }

}

Now go to the URL http://localhost:8080/v2/api-docs where you should see a JSON payload like this.

image.png

This JSON data contains the information about your rest API and all the rest endpoints your API has.

6. Adding swagger-ui

It is tough to read and interpret data in form of JSON for a human. Swagger2 gives a user interface from where you can see all the rest end-points and test them as well.

6.1. Swagger-ui dependency

Add the following maven dependency to your maven file.

<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger-ui</artifactId>
	<version>2.9.2</version>
</dependency>

Now visit http://localhost:8080/swagger-ui.html where you will see a nice UI with the information about your app and all the rest endpoints. You can test the endpoints from here as well.

image.png

6.2. Customizing the API documentation

You can customize the information shown in the documentation by modifying the configuration class we created. After modifications, it should look something like this.

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.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.Collections;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .paths(PathSelectors.ant("/user/*"))
                .apis(RequestHandlerSelectors.basePackage("com.example"))
                .build()
                .apiInfo(appInfo());
    }

    private ApiInfo appInfo(){
        return new ApiInfo(
                "Demo api",
                "Sample api for Codesarray tutorial",
                "1.0",
                "http://localhost/termsOfService",
                 new springfox.documentation.service.Contact("Codesarray","https://codesarray.com","codesarray@gmail.com"),
                "abcd license",
                "http://abcdLicensing.com",
                Collections.emptyList()
        );
    }
}

The paths(PathSelectors.ant("/user/*")) tells swagger to document the rest endpoints which have the user keyword in its path. If you want to document all the endpoints just replace the .ant("/user/*") with .any().

apis(RequestHandlerSelectors.basePackage("com.example")) tells the base package swagger needs to document.

The apiInfo() takes an ApiInfo object as a parameter that contains some basic information about the API which is configured in appInfo().

After adding this configuration the swagger-ui should look like this

image.png

Notice the change in API info. Now it contains much more information and also the basic-error-controller is gone too. Now we only have the endpoints of the user controller.

6.3. Adding annotations to the controller

Swagger2 provides annotations you can add to the controller to add some more information to the documentation. Take a look at the following annotations in our controller.

import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {

    List<User> users = new ArrayList<>();

    @GetMapping("/{id}")
    @ApiOperation(value = "Finds users by id",
                    notes = "Takes the id of user you want to get",
                    response = User.class)
    public User getUser(@ApiParam(value = "Integer id of the user", required = true) @PathVariable int id){
        return users.stream().filter(user -> user.getId() == id).findFirst().get();
    }

    @GetMapping("/")
    public List<User> getUsers(){
        return users;
    }

    @PostMapping("/")
    public User addUser(@RequestBody User user){
        users.add(user);
        return user;
    }

}

@ApiOperation is added at the top of the method it documents the information about the operation performed by the endpoint method.

@ApiParam documents the information about the parameters a rest endpoint takes.

Now we should have some more information about the getUser rest endpoint in our documentation.

image.png

6.4. Adding annotations to the model

Swagger2 also provides annotations you can add in the model class to document information about the model.

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(description = "Details of the user")
public class User {

    @ApiModelProperty(notes = "Id of the user")
    private int id;

    @ApiModelProperty(notes = "Name of the user")
    private String name;

    @ApiModelProperty(notes = "Age of the user")
    private int age;

    @ApiModelProperty(notes = "Email of the user")
    private String email;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

@ApiModel annotation documents the description of the model object.

@ApiModelProperty annotation documents the information about the property of that model.

Now documentation should contain information about the user and its properties in the models section.

image.png

7. Conclusion

Swagger is a nice and easy to use tool to document a rest API. But it comes with a cost, as you have seen whenever you need to add some more info you have to add an annotation in your code which is not a good thing. There are other options too to document an API like Spring REST Docs, etc you can use them as an alternative to swagger.