DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Develop a Spring Boot REST API in AWS: PART 4 (CodePipeline / CI/CD)
  • Breaking Up a Monolithic Database with Kong
  • RESTful Web Services: How To Create a Context Path for Spring Boot Application or Web Service
  • Aggregating REST APIs Calls Using Apache Camel

Trending

  • Start Coding With Google Cloud Workstations
  • Automating Data Pipelines: Generating PySpark and SQL Jobs With LLMs in Cloudera
  • Measuring the Impact of AI on Software Engineering Productivity
  • How to Convert XLS to XLSX in Java
  1. DZone
  2. Data Engineering
  3. Databases
  4. Spring Microservices RESTFul API Documentation With Swagger Part 1

Spring Microservices RESTFul API Documentation With Swagger Part 1

This article explains, how Spring boot Micro-services can be documented using Swagger2

By 
Nitesh Gupta user avatar
Nitesh Gupta
·
Jul. 01, 20 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
24.7K Views

Join the DZone community and get the full member experience.

Join For Free

When back-end APIs are developed and exposed to the client, having good documentation is key. API documentation should be properly structured so that it provides all information related to the API. Without having proper documentation, the client using the API will struggle to access it. If this happens, the API is useless. There are several tools to document the APIs/RESTful Services. However, when you have developed a RESTful service using Spring Boot, then Swagger2 is the obvious choice for documentation because it makes your documentation very easy. 

  1. Swagger is the oldest and most mature spec. 
  2. Supports most languages.
  3. Easy to get started with.
  4. Good community support. 
  5. Has a Maven plugin and is easily configurable with a Spring Boot application.

In this and subsequent articles, we will see how can Swagger2 be configured with a Spring Boot RESTful service. In Part 1, I will show you how to configure your application without security and in Part 2, we'll add security.

Configuration Without Security

The following steps need to be performed to include Swagger in your Spring Boot application and document the API. I will do it for a fresh project 

Step 1 — Create the Project Structure and create artifacts in the correct location.

Creating initial project structure

Step 2 — Add the following Swagger dependencies in your pom.xml file.

Adding dependencies in pom.xmlComplete pom.xml

XML
 




xxxxxxxxxx
1
64


 
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project xmlns="http://maven.apache.org/POM/4.0.0"
3
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
5
    <modelVersion>4.0.0</modelVersion>
6
    <parent>
7
        <groupId>org.springframework.boot</groupId>
8
        <artifactId>spring-boot-starter-parent</artifactId>
9
        <version>2.2.6.RELEASE</version>
10
        <relativePath ></relativePath> <!-- lookup parent from repository -->
11
    </parent>
12
    <groupId>com.demo</groupId>
13
    <artifactId>swagger-config-demo</artifactId>
14
    <version>0.0.1-SNAPSHOT</version>
15
    <name>swagger-config-demo</name>
16
    <description>Swagger Demo</description>
17

          
18
    <properties>
19
        <java.version>1.8</java.version>
20
    </properties>
21

          
22
    <dependencies>
23
        <dependency>
24
            <groupId>org.springframework.boot</groupId>
25
            <artifactId>spring-boot-starter-web</artifactId>
26
        </dependency>
27

          
28
        <dependency>
29
            <groupId>io.springfox</groupId>
30
            <artifactId>springfox-swagger-ui</artifactId>
31
            <version>2.6.1</version>
32

          
33
        </dependency>
34
        <dependency>
35
            <groupId>io.springfox</groupId>
36
            <artifactId>springfox-swagger2</artifactId>
37
            <version>2.6.1</version>
38
        </dependency>
39
        
40

          
41
        <dependency>
42
            <groupId>org.springframework.boot</groupId>
43
            <artifactId>spring-boot-starter-test</artifactId>
44
            <scope>test</scope>
45
            <exclusions>
46
                <exclusion>
47
                    <groupId>org.junit.vintage</groupId>
48
                    <artifactId>junit-vintage-engine</artifactId>
49
                </exclusion>
50
            </exclusions>
51
        </dependency>
52
    </dependencies>
53

          
54
    <build>
55
        <plugins>
56
            <plugin>
57
                <groupId>org.springframework.boot</groupId>
58
                <artifactId>spring-boot-maven-plugin</artifactId>
59
            </plugin>
60
        </plugins>
61
    </build>
62

          
63
</project>
63
</project>



Step 3 — Configuring Swagger in the application. To configure Swagger in the application, we need to create a config file, which will have all Swagger related configurations. I will explain each after this code snippet.

Java
 




xxxxxxxxxx
1
63


 
1
package com.demo.config;
2

          
3
import java.util.ArrayList;
4
import java.util.HashSet;
5
import java.util.List;
6
import java.util.Set;
7

          
8
import org.springframework.context.annotation.Bean;
9
import org.springframework.context.annotation.Configuration;
10
import org.springframework.http.ResponseEntity;
11
import org.springframework.web.bind.annotation.RequestMethod;
12
import org.springframework.web.bind.annotation.RestController;
13

          
14
import springfox.documentation.builders.PathSelectors;
15
import springfox.documentation.builders.RequestHandlerSelectors;
16
import springfox.documentation.builders.ResponseMessageBuilder;
17
import springfox.documentation.schema.ModelRef;
18
import springfox.documentation.service.ApiInfo;
19
import springfox.documentation.spi.DocumentationType;
20
import springfox.documentation.spring.web.plugins.Docket;
21
import springfox.documentation.swagger2.annotations.EnableSwagger2;
22

          
23
@Configuration
24
@EnableSwagger2
25
public class SwaggerConfig {
26
    @Bean
27
    public Docket productApi() {
28
        Set<String> responseProduceType = new HashSet<String>();
29
        responseProduceType.add("application/json");
30
        responseProduceType.add("application/xml");
31
        return new Docket(DocumentationType.SWAGGER_2)
32
                .select().apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
33
                .paths(PathSelectors.any()).build()
34
                .useDefaultResponseMessages(false)
35
                .genericModelSubstitutes(ResponseEntity.class)
36
                .produces(responseProduceType)
37
                .consumes(responseProduceType)
38
                
39
                .apiInfo(apiInfo());
40
                
41
                
42
    }
43

          
44
    private ApiInfo apiInfo() {
45
        @SuppressWarnings("deprecation")
46
        ApiInfo apiInfo = new ApiInfo(
47
                "Item REST API",
48
                "All Item related information",
49
                "API",
50
                "Terms of services",
51
                "nitesh841@gmail.com",
52
                "License of API",
53
                "API License URL");
54
        return apiInfo;
55
        
56
    }
57

          
58
    private Object apiKey() {
59
        // TODO Auto-generated method stub
60
        return null;
61
    }
62
}



In above code snippet, you can see following configuration needs to be done:

  • @EnableSwagger2 - Annotation enables Swagger in the Support in the Class
  • select() - method invocation on Docket bean instance that returns an APISelectBuilder object, which provides the api() method and paths methods that need to be configured. 
  • api() - method filters the Controllers and methods that need to be documented. You can see I am setting the RestController Class as Filter. So, all classes that are annotated with RestController will be filtered.
  • Path() - method acts as an additional filter to generate documentation only for the path starting with  some specific String. In my case, we are allowing all options.

Now, you can see there are few customizations that I had done like:

  • Providing Produce and consume types. Here, I had configured two, "application/json" and "application/xml".
  • ApiInfo - We can set API Details for providing more details to the consumer, like setting name, emailId, terms and conditions, license etc. 
  • SecuritySchema - Will see in the next article (Swagger with Security)
  • SecurityContext - Will see in the next article (Swagger with Security)
  • globalResponseMessage - We can set global Response messages as well for handling errors like 500 and 404, and that will be applicable for all APIs that are being documented

There are a few more customization that can be performed on top of the Docket object.

Step 4 - Once Swagger Configurations are done, Controllers and Model objects need to be documented using available annotations. 

1. Annotations of End Points 

Any Class having the @RestController annotation will be considered as REST API Controllers (Resource).

Java
 




xxxxxxxxxx
1
79


 
1
package com.demo.resource;
2

          
3

          
4
import java.util.List;
5

          
6
import org.springframework.beans.factory.annotation.Autowired;
7
import org.springframework.http.HttpStatus;
8
import org.springframework.http.ResponseEntity;
9
import org.springframework.web.bind.annotation.DeleteMapping;
10
import org.springframework.web.bind.annotation.GetMapping;
11
import org.springframework.web.bind.annotation.PatchMapping;
12
import org.springframework.web.bind.annotation.PathVariable;
13
import org.springframework.web.bind.annotation.PostMapping;
14
import org.springframework.web.bind.annotation.PutMapping;
15
import org.springframework.web.bind.annotation.RequestBody;
16
import org.springframework.web.bind.annotation.RestController;
17

          
18
import com.demo.model.ItemDto;
19
import com.demo.service.ItemService;
20

          
21
import io.swagger.annotations.Api;
22
import io.swagger.annotations.ApiOperation;
23
import io.swagger.annotations.ApiResponse;
24
import io.swagger.annotations.ApiResponses;
25
@RestController
26
@Api(value = "Item Resource to handle all Item related action and queries ")
27
public class ItemResource {
28

          
29
    @Autowired
30
    private ItemService service;
31
    
32
    @GetMapping("/items")
33
    @ApiOperation(value = "Return all Items available in the System", response = List.class)
34
    @ApiResponses(value = {
35
            @ApiResponse(code = 200, message = "Successfully retrieved list"),
36
            @ApiResponse(code = 401, message = "You are not authorized to view the resource"),
37
            @ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"),
38
            @ApiResponse(code = 404, message = "Requested Resource Not Found")
39
    })
40
    public ResponseEntity<List<ItemDto>> fetchItems(){
41
        List<ItemDto> items = service.fetchAll();
42
        return new ResponseEntity<List<ItemDto>>(items, HttpStatus.OK);
43
    }
44
    
45
    @ApiOperation(value = "Return Item for provided Id", response = ItemDto.class)
46
    @GetMapping("/items/{id}")
47
    public ResponseEntity<ItemDto> fetchItemById(@PathVariable long id){
48
        ItemDto ItemDto = service.fetchById(id);
49
        return new ResponseEntity<ItemDto>(ItemDto, HttpStatus.OK);
50
    }
51
    
52
    @PostMapping("/items")
53
    @ApiOperation(value = "Create the Item based on input provided", response = ItemDto.class)
54
    public ResponseEntity<ItemDto> create(@RequestBody ItemDto dto){
55
        ItemDto ItemDto = service.create(dto);
56
        return new ResponseEntity<ItemDto>(ItemDto, HttpStatus.OK);
57
    }
58
    
59
    @ApiOperation(value = "Updated Item for provided Id and with updated details", response = ItemDto.class)
60
    @PutMapping("/items/{id}")
61
    public ResponseEntity<ItemDto> update(@PathVariable Long id, @RequestBody ItemDto dto){
62
        ItemDto itemDto = service.update(dto);
63
        return new ResponseEntity<ItemDto>(itemDto, HttpStatus.OK);
64
    }
65
    
66
    @ApiOperation(value = "Approves the Item for provided Id", response = ItemDto.class)
67
    @PatchMapping("/items/{id}")
68
    public ResponseEntity<ItemDto> approve(@PathVariable Long id){
69
        return null;
70
    }
71
    
72
    @ApiOperation(value = "Delete the Item from System for provided Id", response = ItemDto.class)
73
    @DeleteMapping("/items/{id}")
74
    public ResponseEntity<String> delete(@PathVariable Long id){
75
        service.delete(id);
76
        return new ResponseEntity<String>("Item has been deleted", HttpStatus.OK);
77
    }
78
}



In this Controller/Resource, you can see many annotations. Let's go one by one and see what they are responsible for:

  • @RestController - It is a combination of @Controller and @ResponseBody, and it suggests that this class will be considered as a REST API Controller that will accept all API call requests.
  • @RequestMapping - Class-level annotation that maps requests to items to controller. The method-level @RequestMapping annotations map web requests to the handler methods of the controller. 
  • @GetMapping, @PostMapping, @PatchMapping, @PutMapping, @DeleteMapping - To handle different requests coming from the client. 
  • @API - Class-level annotation to describe the API, and you can use this tag to explain the functionality of API.

RestController example

  • @ApiOperation - Method-level annotation that describes the end point and its response type. You can also override the default response messages of HTTP methods. You can use the @ApiResponse annotation to document other responses, in addition to the regular HTTP 200 OK, like this. 

GetMapping and API annotations

Service Class Implementation

Java
 




xxxxxxxxxx
1
42


 
1
package com.demo.service;
2

          
3
import java.util.ArrayList;
4
import java.util.List;
5
import java.util.stream.Collectors;
6

          
7
import org.springframework.stereotype.Service;
8

          
9
import com.demo.model.ItemDto;
10

          
11
@Service
12
public class ItemService {
13
    List<ItemDto> items = new ArrayList<>();
14
    
15
    public List<ItemDto> fetchAll(){
16
        return items;
17
    }
18
    public ItemDto fetchById(long id) {
19
        return items.stream().filter(dto -> dto.getId() == id).collect(Collectors.toList()).get(0);
20
    }
21
    public ItemDto create (ItemDto dto) {
22
        items.add(dto);
23
        return dto;
24
    }
25
    
26
    public ItemDto update (ItemDto dto) {
27
        items.add(dto);
28
        items.forEach( dto1 ->{
29
            if(dto1.getId() == dto.getId()) {
30
                dto1.setItemCode(dto.getItemCode());
31
                dto1.setItemDescription(dto.getItemDescription());
32
                dto1.setPrice(dto.getPrice());
33
            }
34
        });
35
        return dto;
36
    }
37
    
38
    public void delete(long id) {
39
        items.removeIf(dto -> dto.getId() == id);
40
    }
41
}


 

Spring Boot application 

Java
 




xxxxxxxxxx
1
14


 
1
package com.demo;
2

          
3
import org.springframework.boot.SpringApplication;
4
import org.springframework.boot.autoconfigure.SpringBootApplication;
5

          
6

          
7

          
8
@SpringBootApplication
9
public class SwaggerDemoApplication {
10
    public static void main(String[] args) {
11
        SpringApplication.run(SwaggerDemoApplication.class, args);
12
    }
13
}



2. Annotations for Models 

@ApiModel and @ApiModelProperty can be used to document the Models used in the application. 

  • @ApiModel - Class-level annotation that helps to describe the Model. It has two main fields value and a description.
  • @ApiModelProperty- Field-level annotation that helps to describe the Field in detail. It has many properties; I am highlighting important ones you can use:
    • name - Unique Name
    • value - Detail of field
    • datatype - string, decimal, float, int etc
    • readOnly - true/false
    • example  - Sample Value
Java
 




xxxxxxxxxx
1
86


 
1
package com.demo.model;
2

          
3
import java.io.Serializable;
4

          
5
import io.swagger.annotations.ApiModel;
6
import io.swagger.annotations.ApiModelProperty;
7

          
8
@ApiModel(value = "Item Details", description = "Item Details for perticular Item")
9
public class ItemDto implements Serializable {
10

          
11
    private static final long serialVersionUID = -7844251211618763233L;
12
    @ApiModelProperty(name = "Id", value = "Unique Item Id", dataType = "long", readOnly = true, example = "101")
13
    private long id;
14

          
15
    @ApiModelProperty(name = "itemCode", value = "Unique Item Code", dataType = "long", required = true, example = "BOOK001")
16
    private String itemCode;
17

          
18
    @ApiModelProperty(name = "ItemName", value = "Item Name", dataType = "String", required = true, example = "Microservices architecture")
19
    private String itemName;
20

          
21
    @ApiModelProperty(name = "Item Description", value = "Description of the Item", dataType = "String", example = "Microservices architecture book for building Micro-services")
22
    private String itemDescription;
23

          
24
    @ApiModelProperty(name = "Status", value = "Status of the item", dataType = "long", required = true)
25
    private long status;
26

          
27
    @ApiModelProperty(name = "Price", value = "Price of the item", dataType = "double", required = true, example = "450.40")
28
    private double price;
29

          
30
    public long getId() {
31
        return id;
32
    }
33

          
34
    public void setId(long id) {
35
        this.id = id;
36
    }
37

          
38
    public String getItemCode() {
39
        return itemCode;
40
    }
41

          
42
    public void setItemCode(String itemCode) {
43
        this.itemCode = itemCode;
44
    }
45

          
46
    public String getItemName() {
47
        return itemName;
48
    }
49

          
50
    public void setItemName(String itemName) {
51
        this.itemName = itemName;
52
    }
53

          
54
    public String getItemDescription() {
55
        return itemDescription;
56
    }
57

          
58
    public void setItemDescription(String itemDescription) {
59
        this.itemDescription = itemDescription;
60
    }
61

          
62
    public long getStatus() {
63
        return status;
64
    }
65

          
66
    public void setStatus(long status) {
67
        this.status = status;
68
    }
69

          
70
    public double getPrice() {
71
        return price;
72
    }
73

          
74
    public void setPrice(double price) {
75
        this.price = price;
76
    }
77

          
78
    @Override
79
    public String toString() {
80
        return "ItemDto [id=" + id + ", itemCode=" + itemCode + ", itemName="
81
                + itemName + ", itemDescription=" + itemDescription
82
                + ", status=" + status + ", price=" + price + "]";
83
    }
84

          
85
}



Step 5 - Once endpoint and Model documentation are done, start the Spring Boot application and access the following URL: http://localhost:8080/swagger-ui.html.

Once you access this url, Swager main page will get open which will have all your apis listed which you have documented 

Item REST API

In this page, you can see following things:

  1. Your Controller/Resource Customized name.
  2. All end points which was annotated by @ApiOperation and then you can see the description provided by you at right.
  3. API Info provided in Swagger config file.

When you access POST Method of Items for creating Item:

POST method of items for creating an Item

In this screenshot you can see following 

  1. Response Content Type - Set in Swagger Config. You can chose either XML or JSON. 
  2. Example Value - Picked from Model, documented by you. 
  3. Try Out - There will be a Try Out button. Once you click on it, a request will go to the server and perform the required operation:

Sending request to server for required operation

Swagger Documentation for Item Model 

Swagger documentation for Item model

Summary 

Other than API Documentation, Swagger can also be used for defining your API Specs, and then later, you can perform API Validation as well. As it is integrated with your application, you can easily access the services.

I hope this is helpful. In the next article (Part 2), I will show you Swagger Configurations for adding security, so that only valid users can access Swagger documentation.

API Spring Framework Documentation Spring Boot REST Web Protocols application Annotation microservice

Opinions expressed by DZone contributors are their own.

Related

  • Develop a Spring Boot REST API in AWS: PART 4 (CodePipeline / CI/CD)
  • Breaking Up a Monolithic Database with Kong
  • RESTful Web Services: How To Create a Context Path for Spring Boot Application or Web Service
  • Aggregating REST APIs Calls Using Apache Camel

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!