In the previous chapter, we learned how to develop our Spring Boot application. First, we configured our application to run on the server using IntelliJ. Then, we developed the different parts of the REST application, such as the models and entities, which serve as the objects; the services, which hold the business logic and call the JPA repository to perform CRUD operations in the database; and the controllers, which define the endpoints. We also learned how to apply Redis, which adds a caching mechanism to improve the performance of our REST APIs.
This chapter will focus on creating the documentation for our Spring Boot project. We will focus on configuring springdoc-openapi and Swagger UI and generating documentation on the fly for the endpoints that we have developed.
In this chapter, we will cover the following topics:
The following link will take you to the finished version of this chapter: https://github.com/PacktPublishing/Spring-Boot-and-Angular/tree/main/Chapter-06/superheroes.
In this section, we will configure springdoc-openapi in our Spring Boot application. Since we developed our REST APIs in the previous chapter, the next thing we need to do is create documentation for our endpoints. This is an essential part, especially in the development industry, as this will tell the developers what endpoints can be implemented, what the required requests and their formats are, and what response body to expect when calling the endpoint. This also reduces errors and conflicts regarding the API integration as the available endpoints are transparent. However, the major drawback of creating documentation manually is that it is tedious and error-prone. This is where springdoc-openapi comes into the picture.
First, let’s discuss what springdoc-openapi is. springdoc-openapi is a library that automates the generation of API documentation in Spring Boot projects. This automation is possible as the library uses annotations, class structures, and Spring configurations to identify the available APIs.
springdoc-openapi can generate the necessary documentation in JSON/YAML and HTML APIs that can be viewed with a newly generated URL on our application. It also supports several frameworks and protocols, including the following:
Now, let’s discuss the properties and plugins of springdoc-openapi.
We can modify the behavior and settings of .springdoc-openapi based on our preference. It has different properties, as we can set their values under the application.properties file.
Here are some of the commonly used properties in springdoc-openapi:
springdoc-openapi also has plugins that we can use to generate the documentation. Let’s take a look.
springdoc-openapi-maven-plugin generates a JSON and YAML OpenAPI description during build time. The plugin also works in the integration phase. To enable the plugin, we need to add the following declaration to the <plugin> section of the pom.xml file:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot-maven-plugin.version}</version> <configuration> <jvmArguments> -Dspring.application.admin.enabled=true </jvmArguments> </configuration> <executions> <execution> <goals> <goal>start</goal> <goal>stop</goal> </goals> </execution> </executions> </plugin>
We just added the spring-boot-maven-plugin plugin. Copy the preceding code and paste it into your .pom file.
Now, let’s add version 1.4 of springdoc-openapi-maven-plugin just below the spring-boot-maven-plugin plugin code block:
<plugin> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-maven-plugin</artifactId> <version>1.4</version> <executions> <execution> <id>integration-test</id> <goals> <goal>generate</goal> </goals> </execution> </executions> </plugin>
We can also customize the behavior of openapi-maven-plugin by specifying the following properties:
The following code example shows how to use these properties:
<plugin> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-maven-plugin</artifactId> <version>${version}</version> <executions> <execution> <id>integration-test</id> <goals> <goal>generate</goal> </goals> </execution> </executions> <configuration> <apiDocsUrl> http://localhost:8080/v3/api-docs</apiDocsUrl> <outputFileName>openapi.json</outputFileName> <outputDir>/home/springdoc/output-folder</outputDir> <skip>false</skip> <headers> <header1-key>header1-value</header1-key> </headers> </configuration> </plugin>
In the preceding example XML code, we have added several properties to apply custom configuration for OpenAPI. We have manually set the output filename, directory, and headers for generating the API documentation.
springdoc-openapi-gradle-plugin generates the OpenAPI specification for a Spring Boot application from a Gradle build. To enable the plugin, we must place the following code in our plugins section:
plugins { id "org.springframework.boot" version "${version}" id "org.springdoc.openapi-gradle-plugin" version "${version}" }
Once the plugins and dependencies have been added, the following tasks will be created:
We can also customize the behavior of openapi-graven-plugin by specifying the following properties:
To use these properties, we must specify them using generateOpenApiDocs:
openApi { apiDocsUrl.set("https://localhost:4000/api/docs") outputDir.set(file("$buildDir/docs")) outputFileName.set("swagger-test.json") waitTimeInSeconds.set310) forkProperties.set("-Dspring.profiles.active=special") groupedApiMappings.set( ["https://localhost:8000/v3/api-docs/group-1" to "swagger-group-1.json", "https://localhost:8000/v3/api-docs/group-2" to "swagger-group-2.json"]) }
With that, we have learned about the properties and plugins that we can use in OpenAPI docs. Now, let’s configure the plugin for our Spring Boot application.
Now, we will install and configure springdoc-openapi in our Spring Boot application. First, we must add the dependency to the previous project we made. Go to the pom.xml file and add the following XML code:
<dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>1.6.4</version> </dependency>
After successfully installing the OpenAPI dependency, we can run our Spring Boot project. Once the server has started, we can go to http://localhost:8080/v3/api-docs/ to access the OpenAPI documentation in JSON format. You will see that all of your endpoints and their associated HTTP requests are displayed as JSON objects. The following is a snippet of the generated JSON documentation for our project:
{ "servers": [ { "url": "http://localhost:8080/", "description": "Generated server url" } ], "paths": { "/api/v1/anti-heroes/{id}": { "get": { "tags": [ "anti-hero-controller" ], "operationId": "getAntiHeroById", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ], "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "$ref": "#/components/schemas/AntiHeroDto" …… // other created paths UPDATE DELETE and CREATE Inputs
Here, we can see that the generated JSON object displays the available endpoints in our project. It is shown together with the operation ID, which is the default name of the method; it also specifies the parameters with the types required and the possible responses of the endpoint.
We have used the default URL where OpenAPI can be accessed. We can change the URL using the application’s springdoc.api-docs.path property.properties file. For example, we have set it to springdoc.api-docs.path=rest-docs, which means we can now access the JSON document using http://localhost:8080/rest-docs/.
We can also access the YAML version of the documentation by accessing http://localhost:8080/v3/api-docs.yaml.
With that, we have successfully generated the documentation for our endpoints using springdoc-openapi. In the next section, we will learn how to configure, access, and use Swagger UI.
Swagger UI is a documentation tool that allows users to call the available APIs in your project directly from a browser. This is a more interactive tool that enables a more detailed and practical use of the APIs. Swagger UI is also open source, enabling more communities to support the tool.
Swagger UI is already included under the springdoc-openapi-ui dependency. We have already included the OpenAPI extension code by adding the following code:
<dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>1.6.4</version> </dependency>
The OpenAPI dependency includes the Swagger UI extension; we can access the UI with the following URL: http://localhost:8080/swagger-ui.html. This will open the Swagger UI’s OpenAPI definition page:
Figure 6.1 – The Swagger UI’s OpenAPI definition page
Here, we can see that our Swagger UI has been accessed successfully. Our created endpoints in the Spring Boot project are also displayed, together with their HTTP methods. Let’s discuss the different parts of the Swagger UI documentation.
The first thing we can see in Swagger UI is that it contains text input, alongside the Explore button. This is where Swagger UI gets the list of endpoints it will render. In the preceding example, we can see that the default value is v3/api-docs. This means that the JSON documentation we have generated using the OpenAPI library is being used by Swagger to get the available endpoints.
We can change this and access the URL that contains the OpenAPI documentation in JSON or YAML format. The next component we will see is the list of available endpoints in our project. In the preceding example, the five endpoints we have developed are listed in Swagger UI. This is not a list as the Swagger UI tool is interactive, allowing us to try the available endpoints.
Let’s have a look at the following example:
Figure 6.2 – POST request for anti-heroes
We can expand the /api/v1/anti-heroes endpoint to create a new Anti-Hero object in our database since this is using the POST HTTP method. The schema of the object we need to pass in our request body is specified. It defines both the names and the types of properties. In this case, the Anti-Hero entity has the following schema:
{ "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "firstName": "string", "lastName": "string", "house": "string", "knownAs": "string" }
The possible responses are also specified in the example endpoint. The possible response has a status of 200, which specifies success. It will also return the newly created entity in the database.
We want to test the endpoint and insert some example data into the database. To do this, we must click the Try it out button, which can be found at the top right, and click the Execute button to call the endpoint. Once the API call is successful, we will see the following output:
Figure 6.3 – Response from the POST request
Here, we can see that the API returned successfully as it returned a Code of 200 and the newly created entity in the database.
We can check whether our endpoint has successfully inserted the data into our table by accessing pgAdmin, as shown in the following screenshot:
Figure 6.4 – Verifying whether data has been inserted from the POST request
In the preceding example, we can see that our data has been inserted successfully into our table. Now, we can test the other available endpoints by getting, updating, or deleting the data we have created in the database.
We have successfully navigated through the Swagger UI tool and interacted with the available endpoints, but we can also modify Swagger UI based on our preferences and requirements by using properties, similar to what we can do with the OpenAPI documentation. We can also modify the URL to access Swagger UI; for example, we can place springdoc.swagger-ui.path=/{custom-path}.html in the application.properties file.
The other behavior we can also modify is the sorting behavior of our endpoints. We can change how the endpoints are arranged in the list in terms of alpha (arranged alphanumerically) or method (arranged by methods), or we can use a custom function to change the sorting method. For this, we can place springdoc.swagger-ui.operationsSorter=(sort behavior) in the application.properties file.
In this example, we will use springdoc.swagger-ui.operationsSorter=method. We will see the following output:
Figure 6.5 – Endpoints arranged by methods
As we can see, our endpoints are now arranged by the HTTP methods.
Swagger UI can also be integrated with endpoints that use pagination. We can specify the page number, the size of the list on each page, and the sorting expression. For us to integrate the pagination parameters in Swagger UI, we need to add the springdoc-open-data-rest dependency.
To add the library, we must add the following code to our pom.xml file:
<dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-data-rest</artifactId> <version>1.6.4</version> </dependency>
After successfully adding the library, let’s modify our getAntiHeroes method under AntiHeroesController so that we have a working pagination feature:
…. import org.springframework.data.domain.Pageable; @GetMapping public List<AntiHeroDto> getAntiHeroes(Pageable pageable) { int toSkip = pageable.getPageSize() * pageable.getPageNumber(); var antiHeroList = StreamSupport .stream(service.findAllAntiHeroes().spliterator(), false) .skip(toSkip).limit(pageable.getPageSize()) .collect(Collectors.toList()); return antiHeroList .stream() .map(this::convertToDto) .collect(Collectors.toList()); }
Now, let’s expand api/v1/anti-heroes, which uses the GET method:
Figure 6.6 – GET method for anti-heroes
Here, we can see that the Parameters section has a pageable property and that we can specify the page we want to retrieve, the size of each page, and the sorting expression. Now, we can execute it to retrieve the data from the database.
With this, we have reached the end of this chapter. Let’s recap the valuable things you have learned.
First, you learned about the available features and properties of springdoc-openapi and how to configure and use the OpenAPI specification to generate the JSON and YAML documentation for our API calls. You also learned how to access Swagger UI, an interactive documentation tool for calling APIs directly in a browser. We simulated this to send test calls and modify certain behaviors, such as the domain URL and the sorting order. This newly acquired knowledge for generating documentation for APIs is very useful in real-world applications. This knowledge is used by developers to easily identify the available APIs that can be consumed, as well as their parameters and object responses.
In the next chapter, we will learn about the concept of Cross-Origin Resource Sharing (CORS), Spring Security, and JSON Web Tokens (JWTs).