How to create documentation with Swagger

The blog discusses the importance of documenting RESTful web services and introduces Swagger as a powerful tool for creating, documenting, and visualizing REST APIs. It covers topics such as API evolution, integration with Spring Boot, Maven dependency, and customizing Swagger documentation using annotations.

GraphQL has a role beyond API Query Language- being the backbone of application Integration
background Coditation

How to create documentation with Swagger

In recent years, RESTful web services have gained significant popularity and have become the dominant choice in the web services industry. They have surpassed their more complex counterpart, XML or SOAP, and are now the go-to option for API design and development. An API can be thought of as an agreement between the publisher and consumers to ensure effective communication between the two. This agreement, or contract, outlines the expectations and rules that both parties must follow. Just like any other contract, an API must be well documented to function as expected. This documentation should include details such as 

  • the available endpoints, 
  • the types of operations supported by each endpoint, 
  • the expected input format for an operation, and 
  • the format of the response that will be returned for a given request.

To keep up with changing needs, APIs must evolve over time. In this context, proper documentation is not optional, but rather a crucial aspect of the API's offerings, aimed at providing a better user experience. All this is great, but one question arises and that is how should we document for these API's, And the answer is Swagger, 

Alternatives to Swagger

What is Swagger?

So Swagger is essentially an open-source toolkit that aids in the creation, documentation, and usage of REST APIs, Swagger’s capability to provide API the power to self describe its underlying structure, is what makes it more awesome and tremendously popular.
In this article, we will Create a Rest Application and explore the process of documenting Rest APIs and visualizing it through swagger.
At first, we will integrate Swagger into a Spring Boot application that performs basic Create, Read, Update, and Delete operations for Employees.
If you plan to implement Swagger for APIs you’ve, It’s necessary to first add a maven dependency.


<script src="https://gist.github.com/AP4coditation/65afd4bc22d2846bc1f09cafcf64fee5.js">
</script>

How should we configure it?

To enable Swagger we need to implement a Configuration Class.


<script src="https://gist.github.com/AP4coditation/32d3974c854fe907d3f20773d7fee8d4.js">
</script>

As you can see we have described general Information about our Rest API’s, in function apiInfo(), After this step, when we run the application we will be able to generate JSON representation of our documentation by visiting this link: http://localhost:8080/v2/api-docs


{
	"swagger": "2.0",
	"info": {
		"description": "REST APIs for CRUD Application",
		"version": "1.0"
		"title": "REST APIs",
		"contact": {
			"name":"coditation"
			"url": "www.coditation.com"
			"email": "coditation@gmail.com"
		}.
			"license": {
			"name": "License of API"
			"url": "API license URL"
		},
			"host": "localhost:8080",
			"basePath": "/",
			"tags": [
		{
			"name": "basic-error-controller",
			"description": "Basic Error Controller"
		],
		{
			"name": "employee-controller"
			"description": "Employee Controller"
		}
], 
	"paths": {
		"/api/v1/employees": {
		"get": {
			"tags": [
				"employee-controller"
		], 
			"summary": "getAllEmployees"
			"operationId": "getAllEmployeesUsingGET"
			"produces": [
				"*/*"
		],
			"responses": {
				"200": {
					"description": "OK",
						"schema": {
						"type": "array",
						"items": {
							"Sref":"#/definitions/Employee"
							}

Swagger UI: to see detail and to validate

Swagger provides an in built UI tool , so that you can interact with your documentation much easily by visiting this link: http://localhost:8080/swagger-ui/

———————————————————————————————————————

Please note: you can only see above link if Swagger is configured correctly 

———————————————————————————————————————

Customizing Swagger Documentation

Swagger provides us the flexibility to customize the generated REST documentation according to our needs. to customize the documentation we will need to use some swagger annotations with your functions in the controller.
Some Important Swagger Annotations are as follows :

  • @ApiModel - Can be used to customize information about Model Class.
  • @ApiModelProperty - Can be used to provide Extra information about Fields in Model Class.
  • @ApiResponse - Provides with the Response of particular API
  • @ApiOperation - Can be used to provides additional information about API
  • @ApiParam - Can be used to get information about parameters used in API

Swagger Annotations In Action


<script src="https://gist.github.com/AP4coditation/cea2d588bd41be346f91a30b3b9cd98c.js">
</script>

Incorporating @ApiOperation, @ApiResponse & @ApiParam with your code provides you with following documentation , where we can see customized information is being displayed with associated API

On the other hand if we use @ApiModel & @ApiModelProperty annotations


<script src="https://gist.github.com/AP4coditation/7d100e95920a0132abf55d87e3719318.js">
</script>

We will get following output about our Model Class from Swagger

As you can see all properties in model class has description associated with it and also the mandatory field has * associated with it.

Conclusion

Swagger is a powerful tool that compliments your API’s. It offers complete flexibility in automating the documentation process for API’s, and it will be very helpful for the new software engineers that would be joining your team to understand the API structure very clearly and rapidly.


JSON
{
  "swagger": "2.0",
  "info": {
    "description": "REST APIs for CRUD Application",
    "version": "1.0",
    "title": "REST APIs",
    "contact": {
      "name": "coditation",
      "url": "www.coditation.com",
      "email": "coditation@gmail.com"
    },
    "license": {
      "name": "License of API",
      "url": "API license URL"
    }
  },
  "host": "localhost:8080",
  "basePath": "/",
  "tags": [
    {
      "name": "basic-error-controller",
      "description": "Basic Error Controller"
    },
    {
      "name": "employee-controller",
      "description": "Employee Controller"
    }
  ],
  "paths": {
    "/api/v1/employees": {
      "get": {
        "tags": [
          "employee-controller"
        ],
        "summary": "Get all Employees with this REST API",
        "operationId": "getAllEmployeesUsingGET",
"produces": [
          "*/*"
        ],
        "responses": {
          "200": {
            "description": "All Employees Retrived Successfully",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/EmployeeTable"
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        }
      },
      "post": {
        "tags": [
          "employee-controller"
        ],
        "summary": "createEmployee",
        "operationId": "createEmployeeUsingPOST",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "employee",
"description": "employee",
            "required": true,
            "schema": {
              "$ref": "#/definitions/EmployeeTable"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/EmployeeTable"
            }
          },
          "201": {
            "description": "Created"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        }
      }
    },
    "/api/v1/employees/{id}": {
      "get": {
        "tags": [
          "employee-controller"
        ],
        "summary": "Get particular Employee using this API",
        "operationId": "getEmployeeByIdUsingGET",
        "produces": [
          "*/*"
        ],
        "parameters": [
{
            "name": "id",
            "in": "path",
            "description": "EmployeeId",
            "required": true,
            "type": "integer",
            "default": 44,
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": "The Response is Retrived Successfully",
            "schema": {
              "$ref": "#/definitions/EmployeeTable"
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        }
      },
      "put": {
        "tags": [
          "employee-controller"
        ],
        "summary": "updateEmployee",
        "operationId": "updateEmployeeUsingPUT",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
 "parameters": [
          {
            "in": "body",
            "name": "employeeDetails",
            "description": "employeeDetails",
            "required": true,
            "schema": {
              "$ref": "#/definitions/EmployeeTable"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/EmployeeTable"
            }
          },
          "201": {
            "description": "Created"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        }
      },


"delete": {
        "tags": [
          "employee-controller"
        ],
        "summary": "deleteEmployee",
        "operationId": "deleteEmployeeUsingDELETE",
        "produces": [
          "*/*"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "boolean"
              }
            }
          },
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      }
    },
    "/error": {
      "get": {
        "tags": [
          "basic-error-controller"
        ],
        "summary": "error",
        "operationId": "errorUsingGET",
        "produces": [
          "*/*"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object"
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        }
      },
      "head": {
        "tags": [
          "basic-error-controller"
        ],
        "summary": "error",
        "operationId": "errorUsingHEAD",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object"
              }
            }
          },
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "basic-error-controller"
        ],
        "summary": "error",
        "operationId": "errorUsingPOST",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object"
              }
            }
          },
          "201": {
            "description": "Created"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        }
      },
      "put": {
        "tags": [
          "basic-error-controller"
        ],
        "summary": "error",
        "operationId": "errorUsingPUT",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object"
            }
            }
          },
          "201": {
            "description": "Created"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        }
      },
      "delete": {
        "tags": [
          "basic-error-controller"
        ],
        "summary": "error",
        "operationId": "errorUsingDELETE",
        "produces": [
          "*/*"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object"
              }
            }
          },
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      },
      "options": {
        "tags": [
          "basic-error-controller"
        ],
        "summary": "error",
        "operationId": "errorUsingOPTIONS",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object"
              }
            }
          },
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      },
      "patch": {
        "tags": [
          "basic-error-controller"
        ],
        "summary": "error",
        "operationId": "errorUsingPATCH",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object"
              }
            }
          },
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        }
      }
    }
  },
  "definitions": {
    "EmployeeTable": {
      "type": "object",
      "required": [
        "id"
      ],
      "properties": {
        "emailId": {
          "type": "string",
          "description": "EmailId"
        },
        "firstName": {
          "type": "string",
          "description": "EmployeeFirstName"
        },
        "id": {
          "type": "integer",
          "format": "int64",
          "description": "EmployeeId"
        },
        "lastName": {
          "type": "string",
          "description": "EmployeeLastName"
        }
      },
      "title": "EmployeeTable",
      "description": "Additional information about table"
    },
    "ModelAndView": {
      "type": "object",
      "properties": {
        "empty": {
          "type": "boolean"
        },
        "model": {
          "type": "object"
        },
        "modelMap": {
          "type": "object",
          "additionalProperties": {
            "type": "object"
          }
        },
        "reference": {
          "type": "boolean"
        },
        "status": {
          "type": "string",
          "enum": [
            "ACCEPTED",
            "ALREADY_REPORTED",
            "BAD_GATEWAY",
            "BAD_REQUEST",
            "BANDWIDTH_LIMIT_EXCEEDED",
            "CHECKPOINT",
            "CONFLICT",
            "CONTINUE",
            "CREATED",
            "DESTINATION_LOCKED",
            "EXPECTATION_FAILED",
            "FAILED_DEPENDENCY",
            "FORBIDDEN",
            "FOUND",
            "GATEWAY_TIMEOUT",
            "GONE",
            "HTTP_VERSION_NOT_SUPPORTED",
            "IM_USED",
            "INSUFFICIENT_SPACE_ON_RESOURCE",
            "INSUFFICIENT_STORAGE",
            "INTERNAL_SERVER_ERROR",
            "I_AM_A_TEAPOT",
            "LENGTH_REQUIRED",
            "LOCKED",
            "LOOP_DETECTED",
            "METHOD_FAILURE",
            "METHOD_NOT_ALLOWED",
            "MOVED_PERMANENTLY",
            "MOVED_TEMPORARILY",
            "MULTIPLE_CHOICES",
            "MULTI_STATUS",
            "NETWORK_AUTHENTICATION_REQUIRED",
            "NON_AUTHORITATIVE_INFORMATION",
            "NOT_ACCEPTABLE",
            "NOT_EXTENDED",
            "NOT_FOUND",
            "NOT_IMPLEMENTED",
            "NOT_MODIFIED",
            "NO_CONTENT",
            "OK",
            "PARTIAL_CONTENT",
            "PAYLOAD_TOO_LARGE",
            "PAYMENT_REQUIRED",
            "PERMANENT_REDIRECT",
            "PRECONDITION_FAILED",
            "PRECONDITION_REQUIRED",
            "PROCESSING",
            "PROXY_AUTHENTICATION_REQUIRED",
            "REQUESTED_RANGE_NOT_SATISFIABLE",
            "REQUEST_ENTITY_TOO_LARGE",
            "REQUEST_HEADER_FIELDS_TOO_LARGE",
            "REQUEST_TIMEOUT",
            "REQUEST_URI_TOO_LONG",
            "RESET_CONTENT",
            "SEE_OTHER",
            "SERVICE_UNAVAILABLE",
            "SWITCHING_PROTOCOLS",
            "TEMPORARY_REDIRECT",
            "TOO_EARLY",
            "TOO_MANY_REQUESTS",
            "UNAUTHORIZED",
            "UNAVAILABLE_FOR_LEGAL_REASONS",
            "UNPROCESSABLE_ENTITY",
            "UNSUPPORTED_MEDIA_TYPE",
            "UPGRADE_REQUIRED",
            "URI_TOO_LONG",
            "USE_PROXY",
            "VARIANT_ALSO_NEGOTIATES"
          ]
        },
        "view": {
          "$ref": "#/definitions/View"
        },
        "viewName": {
          "type": "string"
        }
      },
      "title": "ModelAndView"
    },
    "View": {
      "type": "object",
      "properties": {
        "contentType": {
          "type": "string"
        }
      },
      "title": "View"
    }
  }
}

Hello There, I am Sachin Sonone, a software developer who loves tackling complex problems. When I'm not coding, you may often find me engrossed in a game of chess. I thrive on challenging work that pushes my problem-solving and technical skills to the limit.

Want to receive update about our upcoming podcast?

Thanks for joining our newsletter.
Oops! Something went wrong.