본문 바로가기
  • AI (Artificial Intelligence)
Industry 4.0/APIs

Swagger – Spring REST Example

by 로샤스 2020. 8. 6.

Ref. https://howtodoinjava.com/swagger2/swagger-spring-mvc-rest-example/

Now a days REST and Microservices have got a lot of momentum. At the same time, actual REST specification does not suggest any standard way to document the REST APIs that we are going to expose [like WSDL for SOAP]. As a result, everybody is documenting their APIs in their own way, resulting a gap in common structure which all can easily follow, understand and use. We need to have a common pattern and tool.

Swagger (backed by companies like Google, IBM, Microsoft) does this same job of filling the gap of common documentation style. In this tutorial, we will learn to use Swagger to generate REST API docs using swagger 2 annotations.

Table of Contents What is Swagger Project Structure and Technology Stack Create REST APIs Swagger2 Configuration Swagger2 Annotations Demo

 

What is Swagger

Swagger (now the “Open API Initiative”) is a specification and framework for describing REST APIs using a common language that everyone can understand. There are other available frameworks that have gained some popularity, such as RAML, Summation etc. but Swagger is most popular at this point of time considering its features and acceptance among the developer community.

It offers both human readable and machine readable format of documentation. It provides both JSON and UI support. JSON can be used as machine readable format and Swagger-UI is for visual display which is easy for humans to understand by just browsing the api documentation.

 

Project Structure and Technology Stack

The folder structure of project is :

Swagger2 Project Structure

We will use the below technologies for this demo.

  1. Eclipse as IDE
  2. Maven as build tool
  3. Spring Boot as application framework
  4. Spring Rest as REST API framework
  5. Swagger2 as REST documentation framework
  6. Java 1.8

 

Create REST APIs

We will first create some REST APIs which will be used for demonstration of Swagger documentation capability. We will use the Spring boot style of exposing rest API for faster development time.

  1. Create a Spring boot project from Spring Boot initializer portal with Web, Rest Repositories, Actuator dependencies. Give other maven GAV coordinates and download the project. This screen will look like:
    Spring Boot REST Project Generation

    Unzip and import the project into Eclipse as existing maven project. In this step, all necessary dependencies will be downloaded from maven repository. Perform a fresh mvn clean install at this step so that all spring-boot related artifacts got downloaded properly.

  2. Open application.properties and add below property. This will start the application in /swagger2-demo context path.

    server.contextPath=/swagger2-demo

  3. Add one REST controller Swagger2DemoRestController which will provide basic REST based functionalities on Student entity.

    Swagger2DemoRestController.java

    package com.example.springbootswagger2.controller;

     

    import java.util.ArrayList;

    import java.util.List;

    import java.util.stream.Collectors;

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

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

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

    import com.example.springbootswagger2.model.Student;

     

    @RestController

    public class Swagger2DemoRestController {

     

        List<Student> students = new ArrayList<Student>();

        {

            students.add(new Student("Sajal", "IV", "India"));

            students.add(new Student("Lokesh", "V", "India"));

            students.add(new Student("Kajal", "III", "USA"));

            students.add(new Student("Sukesh", "VI", "USA"));

        }

     

        @RequestMapping(value = "/getStudents")

        public List<Student> getStudents() {

            return students;

        }

     

        @RequestMapping(value = "/getStudent/{name}")

        public Student getStudent(@PathVariable(value = "name") String name) {

            return students.stream().filter(x -> x.getName().equalsIgnoreCase(name)).collect(Collectors.toList()).get(0);

        }

     

        @RequestMapping(value = "/getStudentByCountry/{country}")

        public List<Student> getStudentByCountry(@PathVariable(value = "country") String country) {

            System.out.println("Searching Student in country : " + country);

            List<Student> studentsByCountry = students.stream().filter(x -> x.getCountry().equalsIgnoreCase(country))

                    .collect(Collectors.toList());

            System.out.println(studentsByCountry);

            return studentsByCountry;

        }

     

        @RequestMapping(value = "/getStudentByClass/{cls}")

        public List<Student> getStudentByClass(@PathVariable(value = "cls") String cls) {

            return students.stream().filter(x -> x.getCls().equalsIgnoreCase(cls)).collect(Collectors.toList());

        }

    }

    Student.java

    package com.example.springbootswagger2.model;

     

    public class Student {

         

        private String name;

        private String cls;

        private String country;

     

        public Student(String name, String cls, String country) {

            super();

            this.name = name;

            this.cls = cls;

            this.country = country;

        }

     

        public String getName() {

            return name;

        }

     

        public String getCls() {

            return cls;

        }

     

        public String getCountry() {

            return country;

        }

     

        @Override

        public String toString() {

            return "Student [name=" + name + ", cls=" + cls + ", country=" + country + "]";

        }

    }

  4. Start the application as Spring boot application. Test couple of REST Endpoints to check if they are working fine:
    • http://localhost:8080/swagger2-demo/getStudents
    • http://localhost:8080/swagger2-demo/getStudent/sajal
    • http://localhost:8080/swagger2-demo/getStudentByCountry/india
    • http://localhost:8080/swagger2-demo/getStudentByClass/v

 

Swagger2 Configuration

Our REST APIs are ready. Now add swagger 2 support to the project.ff

Add Swagger2 Maven Dependencies

Open pom.xml file of the spring-boot-swagger2 project and add below two swagger related dependencies i.e. springfox-swagger2 and springfox-swagger-ui.

<dependency>

       <groupId>io.springfox</groupId>

       <artifactId>springfox-swagger2</artifactId>

       <version>2.6.1</version>

   </dependency>

 

   <dependency>

       <groupId>io.springfox</groupId>

       <artifactId>springfox-swagger-ui</artifactId>

       <version>2.6.1</version>

   </dependency>

Actually swagger API has couple of varieties and maintained in different artifacts. Today we will use the springfox because this version adapts well with any spring based configurations. We can try other configurations also easily and that should give same functionality – with no/little change in configuration.

Add Swagger2 Configuration

Add the below configuration in the code base. To help you understand the configuration, I have added inline comments.

package com.example.springbootswagger2.configuration;

 

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.google.common.base.Predicates;

import springfox.documentation.builders.RequestHandlerSelectors;

import springfox.documentation.spi.DocumentationType;

import springfox.documentation.spring.web.plugins.Docket;

import springfox.documentation.swagger2.annotations.EnableSwagger2;

 

@Configuration

@EnableSwagger2

public class Swagger2UiConfiguration extends WebMvcConfigurerAdapter

{

    @Bean

    public Docket api() {

        // @formatter:off

        //Register the controllers to swagger

        //Also it is configuring the Swagger Docket

        return new Docket(DocumentationType.SWAGGER_2).select()

                // .apis(RequestHandlerSelectors.any())

                .apis(Predicates.not(RequestHandlerSelectors.basePackage("org.springframework.boot")))

                // .paths(PathSelectors.any())

                // .paths(PathSelectors.ant("/swagger2-demo"))

                .build();

        // @formatter:on

    }

 

    @Override

    public void addResourceHandlers(ResourceHandlerRegistry registry)

    {

        //enabling swagger-ui part for visual documentation

        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");

    }

}

Verify Swagger2 JSON Format Docs

Do maven build and Start the server. Open the link http://localhost:8080/swagger2-demo/v2/api-docs and it should give the entire documentation in JSON format. This is not that much easy to read and understand, actually Swagger has provided this to be used in other systems like API management tools now a days popular, which provides the functionality like API gateways, API caching, API documentation etc.

JSON documentationVerify Swagger2 UI Docs

Open http://localhost:8080/swagger2-demo/swagger-ui.html to see the Swagger UI documentation in the browser.

Swagger2 UI Docs without Annotations

 

Swagger2 Annotations

The default generated API docs are good but they lack detailed API level information. Swagger has provided few annotations to add this detailed information to the APIs. e.g.

  1. @Api – We can add this Annotation to the controller to add basic information regarding the controller.

    @Api(value = "Swagger2DemoRestController", description = "REST APIs related to Student Entity!!!!")

    @RestController

    public class Swagger2DemoRestController {

        ...

    }

  2. @ApiOperation and @ApiResponses – We can add these annotations to any rest method in the controller to add basic information related to that method. e.g.

    @ApiOperation(value = "Get list of Students in the System ", response = Iterable.class, tags = "getStudents")

    @ApiResponses(value = {

                @ApiResponse(code = 200, message = "Success|OK"),

                @ApiResponse(code = 401, message = "not authorized!"),

                @ApiResponse(code = 403, message = "forbidden!!!"),

                @ApiResponse(code = 404, message = "not found!!!") })

     

    @RequestMapping(value = "/getStudents")

    public List<Student> getStudents() {

        return students;

    }

    Here we can add tags to methods to add some grouping in the swagger-ui.

  3. @ApiModelProperty – This annotation is used in the Model property to add some description to the Swagger output for that model attribute. e.g.

    @ApiModelProperty(notes = "Name of the Student",name="name",required=true,value="test name")

    private String name;

Controller and Model class code after adding swagger2 annotations.

Swagger2DemoRestController.java

package com.example.springbootswagger2.controller;

 

import java.util.ArrayList;

import java.util.List;

import java.util.stream.Collectors;

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

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

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

import com.example.springbootswagger2.model.Student;

import io.swagger.annotations.Api;

import io.swagger.annotations.ApiOperation;

import io.swagger.annotations.ApiResponse;

import io.swagger.annotations.ApiResponses;

 

@Api(value = "Swagger2DemoRestController", description = "REST Apis related to Student Entity!!!!")

@RestController

public class Swagger2DemoRestController {

 

    List<Student> students = new ArrayList<Student>();

    {

        students.add(new Student("Sajal", "IV", "India"));

        students.add(new Student("Lokesh", "V", "India"));

        students.add(new Student("Kajal", "III", "USA"));

        students.add(new Student("Sukesh", "VI", "USA"));

    }

 

    @ApiOperation(value = "Get list of Students in the System ", response = Iterable.class, tags = "getStudents")

    @ApiResponses(value = {

            @ApiResponse(code = 200, message = "Suceess|OK"),

            @ApiResponse(code = 401, message = "not authorized!"),

            @ApiResponse(code = 403, message = "forbidden!!!"),

            @ApiResponse(code = 404, message = "not found!!!") })

 

    @RequestMapping(value = "/getStudents")

    public List<Student> getStudents() {

        return students;

    }

 

    @ApiOperation(value = "Get specific Student in the System ", response = Student.class, tags = "getStudent")

    @RequestMapping(value = "/getStudent/{name}")

    public Student getStudent(@PathVariable(value = "name") String name) {

        return students.stream().filter(x -> x.getName().equalsIgnoreCase(name)).collect(Collectors.toList()).get(0);

    }

 

    @ApiOperation(value = "Get specific Student By Country in the System ", response = Student.class, tags = "getStudentByCountry")

    @RequestMapping(value = "/getStudentByCountry/{country}")

    public List<Student> getStudentByCountry(@PathVariable(value = "country") String country) {

        System.out.println("Searching Student in country : " + country);

        List<Student> studentsByCountry = students.stream().filter(x -> x.getCountry().equalsIgnoreCase(country))

                .collect(Collectors.toList());

        System.out.println(studentsByCountry);

        return studentsByCountry;

    }

 

    // @ApiOperation(value = "Get specific Student By Class in the System ",response = Student.class,tags="getStudentByClass")

    @RequestMapping(value = "/getStudentByClass/{cls}")

    public List<Student> getStudentByClass(@PathVariable(value = "cls") String cls) {

        return students.stream().filter(x -> x.getCls().equalsIgnoreCase(cls)).collect(Collectors.toList());

    }

}

Student.java

package com.example.springbootswagger2.model;

 

import io.swagger.annotations.ApiModelProperty;

 

public class Student

{

    @ApiModelProperty(notes = "Name of the Student",name="name",required=true,value="test name")

    private String name;

 

    @ApiModelProperty(notes = "Class of the Student",name="cls",required=true,value="test class")

    private String cls;

 

    @ApiModelProperty(notes = "Country of the Student",name="country",required=true,value="test country")

    private String country;

 

    public Student(String name, String cls, String country) {

        super();

        this.name = name;

        this.cls = cls;

        this.country = country;

    }

 

    public String getName() {

        return name;

    }

 

    public String getCls() {

        return cls;

    }

 

    public String getCountry() {

        return country;

    }

 

    @Override

    public String toString() {

        return "Student [name=" + name + ", cls=" + cls + ", country=" + country + "]";

    }

}

 

Demo

Now when our REST APIs are properly annotated, let’s see the final output. Open http://localhost:8080/swagger2-demo/swagger-ui.html to see the Swagger ui documentation in the browser.

Final Swagger2 REST API Output

That’s all about to create REST API documentation using swagger2 using a spring boot application. Drop me your questions in comments section.

Download Source code

Happy Learning !!

댓글