When it comes to modern web development, creating well-documented APIs is crucial for facilitating smooth communication between different software components. What we truly need is a solution that can swiftly identify all APIs within a project, present them in a user-friendly interface, and generate comprehensive documentation. Enter Swagger – a tool tailored precisely to address this challenge head-on.
Let’s proceed with the article structured around the following focal points:
- Understanding Swagger and OpenAPI.
- Integrating Swagger into a Spring Boot Project
- Crafting and Testing RestAPI using SwaggerUI
To kick things off, let’s provide a concise overview of Swagger:
Understanding Swagger and OpenAPI
Swagger stands as an open-source software designed to facilitate the creation, documentation, and utilization of RESTful web services. It establishes a standard protocol for crafting documentation for RESTful API services and furnishes an intuitive interface for API users. Furthermore, Swagger doubles as a tool for testing and validating API services. While many platforms can leverage Swagger, our focus in this article revolves around its integration within a Java Spring Boot project.
Moreover, OpenAPI emerges as a specification – a comprehensive document delineating intricate system designs and specifications in detail. Formerly recognized as the Swagger specification, it has transitioned into OpenAPI. This specification empowers the explicit definition, documentation, and discovery of APIs, with development spearheaded by Swagger.
Integrating Swagger into a Spring Boot Project
Embedding Swagger into a Spring Boot project proves to be a straightforward endeavor. Let’s embark on this journey by initiating a new Spring Boot project from scratch. We’ll craft our project with meticulous attention to detail, adhering to the following specifications:
The following will be our initial dependencies:
dependencies {
implementation "org.springframework.boot:spring-boot-devtools"
implementation "org.springframework.boot:spring-boot-starter-actuator"
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
}
The next logical step involves incorporating the requisite dependency for Swagger into our project. To achieve this, we’ll navigate to the build.gradle file and introduce the necessary dependency.
dependencies {
implementation 'org.springdoc:springdoc-openapi-ui:1.8.0'
}
With the essential dependency added, our next task involves defining a @Bean by crafting a Config class. This class serves to enable our Spring Boot project to define and manage configurations effectively, ensuring seamless integration.
package com.example.keitaro_swagger.config;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@OpenAPIDefinition
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI baseOpenAPI(){
return new OpenAPI()
.info(new Info()
.title("Keitaro Spring Project OpenAPI Docs example")
.version("1.0.0").description("Documentation description"));
}
}
The content of the OpenApiConfig class is meticulously designed to configure the fundamental settings for Swagger/OpenAPI documentation within a Spring Boot application. It encapsulates the essential configurations necessary for documentation creation. Parameters such as title, version, and description, meticulously defined within this class, will prominently feature in the Swagger interface.
Having executed these vital configurations, it’s time to launch our project and navigate to http://localhost:8080/swagger-ui/index.html. Assuming the settings are in order, we’ll be greeted by the following web interface:
Here, the title, version, and description specified within the Config class will be prominently displayed. With Swagger seamlessly integrated into our Spring Boot project, we’re equipped to efficiently manage and document our APIs with ease.
Crafting and Testing RestAPI using SwaggerUI
Traditionally, when it comes to testing the RestAPIs we construct, Postman reigns supreme as the go-to tool, enabling us to meticulously craft and execute essential queries. But what if I told you that SwaggerUI could offer a compelling alternative?
To explore this possibility, let’s create a basic RestAPI. We’ll begin by crafting a Controller and entity classes.
package com.example.keitaro_swagger.controller;
import com.example.keitaro_swagger.domain.Example;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequiredArgsConstructor
@RequestMapping("swaggerExample")
public class ExampleController {
@GetMapping()
public List<Example> getExamples() {
return Example.dummyExamples();
}
}
package com.example.keitaro_swagger.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Example {
private Integer exampleId;
private String exampleName;
public static List<Example> dummyExamples(){
Example e1 = new Example(1,"Example 1");
Example e2 = new Example(2,"Example 2");
Example e3 = new Example(3,"Example 3");
return List.of(e1,e2,e3);
}
}
The ExampleController class above delineates a simplistic service, populated with three dummyExamples for testing purposes. Upon accessing http://localhost:8080/swaggerExample via a GET query, these three examples will be returned.
Upon completing the setup, we’ll navigate to the Swagger interface. Here, Swagger will intuitively present us with a structured overview of the methods associated with Spring Objects annotated with @RestController, effectively generating documentation on the fly.
However, can we refine this documentation further? For instance, while Swagger provides a response document for the 200 code, can we tailor it to our specific needs? Indeed, we can. Leveraging OpenAPI annotations, we can enrich our documentation with detailed explanations for each method. To streamline this process and avoid redundancy, we’ll implement the necessary updates in the Config and Controller classes:
package com.example.keitaro_swagger.config;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequiredArgsConstructor
@RequestMapping("swaggerExample")
public class ExampleController {
@GetMapping()
@Operation(
description = "Get Examples Service",
responses = {
@ApiResponse(responseCode = "400",ref = "badRequest"),
@ApiResponse(responseCode = "500",ref = "internalServerError"),
@ApiResponse(responseCode = "200",ref = "successfulResponse")
}
)
public List<Example> getExamples() {
return Example.dummyExamples();
}
}
package com.example.keitaro_swagger.config;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.examples.Example;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.media.Content;
import io.swagger.v3.oas.models.responses.ApiResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@OpenAPIDefinition
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI baseOpenAPI(){
ApiResponse badRequest = new ApiResponse().content(
new Content().addMediaType("application/json",
new io.swagger.v3.oas.models.media.MediaType().addExamples("default",
new Example().value("{\"code\" : 400, \"status\" : \"Bad Request\", \"Message\" : \"Bad Request\"}"))));
ApiResponse internalServerError = new ApiResponse().content(
new Content().addMediaType("application/json",
new io.swagger.v3.oas.models.media.MediaType().addExamples("default",
new Example().value("{\"code\" : 500, \"status\" : \"internalServerError\", \"Message\" : \"internalServerError\"}"))));
ApiResponse successfulResponse = new ApiResponse().content(
new Content().addMediaType("application/json",
new io.swagger.v3.oas.models.media.MediaType().addExamples("default",
new Example().value("{\"name\":\"string\",\"surname\":\"string\",\"age\":0}"))));
Components components = new Components();
components.addResponses("badRequest",badRequest);
components.addResponses("internalServerError",internalServerError);
components.addResponses("successfulResponse",successfulResponse);
return new OpenAPI()
.info(new Info()
.title("Keitaro Spring Project OpenAPI Docs example")
.version("1.0.0").description("Documentation description"));
}
}
In essence, we’ve crafted a simple documentation for responses corresponding to 200–400–500 codes, which we can apply universally across all methods. With these modifications in place, let’s relaunch the project and observe the Swagger interface.
Finally, let’s put our setup to the test by sending requests through the SwaggerUI interface. Clicking the “try it out” button initiates a request to the getExamples method, displaying the resulting response code and body – very similar to Postman’s functionality.
In this blog post, we’ve explored how to integrate Springdoc OpenAPI UI with Spring Boot. By leveraging Springdoc, developers can effortlessly generate comprehensive API documentation for their Spring Boot applications, fostering better collaboration and understanding among teams. Whether you’re building a simple RESTful service or a complex microservices architecture, Springdoc OpenAPI UI is a valuable tool for simplifying API documentation and improving developer productivity.