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.
- Eclipse as IDE
- Maven as build tool
- Spring Boot as application framework
- Spring Rest as REST API framework
- Swagger2 as REST documentation framework
- 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.
- 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.
- Open application.properties and add below property. This will start the application in /swagger2-demo context path.
server.contextPath=/swagger2-demo
- 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 + "]";
}
}
- 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.
- @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 {
...
}
- @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.
- @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.
Happy Learning !!
'Industry 4.0 > APIs' 카테고리의 다른 글
Make a README (README.md) (0) | 2020.08.06 |
---|---|
REST API v3 for GitHub Developer (0) | 2020.08.06 |
Search API Parameters (0) | 2020.08.06 |
The Markdown elements outlined in John Gruber's design document (0) | 2020.08.06 |
Paging, sorting, filtering and retrieving specific fields in your RESTful API (0) | 2020.08.06 |
댓글