Spring Boot 4 Microservices Project: Open API Docs and Swagger UI (Part 13)
When building distributed microservices, external clients and other developers need a clear, interactive contract defining available endpoints, expected request objects, and response structures. Instead of relying on manual documentation, we use the OpenAPI Specification and Swagger tooling to auto-generate and expose service contracts. This chapter covers adding Swagger documentation to individual Spring Boot microservices (user-service, device-service), customizing the generated metadata (titles, descriptions, contact details, and licenses), and routing these documentation endpoints securely through the central API Gateway.
1. Why Do We Need API Documentation?
In a monolithic architecture, internal method calls make service contracts explicit. In a microservices ecosystem, services are isolated across networks, often managed by different teams or consumed by third-party clients.
- Communication Gap: External clients or frontend developers need to know exact URL paths, HTTP methods, query parameters, and payload schemas without reading raw source code.
- Third-Party Integration Standards: Industry giants (such as Stripe) provide clean, interactive documentation splitting resources into objects (
accounts,customers) with detailed attributes, example requests, and responses. - The Solution: Automate this process using industry standards so documentation updates automatically as code changes.
2. Core Mental Model: OpenAPI vs. Swagger
A common point of confusion among developers is the distinction between OpenAPI and Swagger. They are often used interchangeably, but they represent different layers of the ecosystem:
3. Adding Swagger to the User Service
To enable OpenAPI and Swagger UI in our first microservice (user-service), we add the official Spring Doc starter dependency to the Maven configuration.
Step 1: Add the Dependency in pom.xml
Open the pom.xml file of the user-service and add the SpringDoc OpenAPI starter web MVC UI dependency:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.x.x</version> <!-- Use latest stable version compatible with Spring Boot 4 -->
</dependency>
Step 2: Bootstrapping and Default Endpoints
Start your Docker containers and launch the user-service. Inspecting the application startup logs reveals that documentation endpoints are enabled by default:
2025-XX-XX ... INFO : SpringDoc v3 API docs endpoint is enabled by default at /v3/api-docs
2025-XX-XX ... INFO : Swagger UI endpoint is enabled by default at /swagger-ui/index.html
- Graphical UI: Navigate to
http://localhost:8080/swagger-ui/index.htmlto view the interactive Swagger interface displaying all endpoints (User Controller) with "Try it out" capabilities. - Raw JSON Specification: Navigate to
http://localhost:8080/v3/api-docsto retrieve the machine-readable JSON representation of the API contract.
4. Customizing Swagger Documentation with Java Configuration
Out-of-the-box documentation displays a generic title (OpenAPI definition). To make it professional and brand-specific, we create a configuration class within user-service.
Step 1: Create OpenApiConfig.java
Create a new package named config inside src/main/java/com/.../userservice/ and add the configuration class:
package com.example.userservice.config;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI userServiceOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("User Service API")
.description("User service API documentation for the Home Energy Tracker system")
.version("v1.0.0")
.contact(getContactInfo())
.license(getLicenseInfo()));
}
private static Contact getContactInfo() {
return new Contact()
.name("Development Team")
.url("https://www.homeenergytracker.com")
.email("support@homeenergytracker.com");
}
private static License getLicenseInfo() {
return new License()
.name("Creative Commons Attribution 4.0 International")
.url("https://creativecommons.org/licenses/by/4.0/");
}
}
Step 2: Verify Customization
Restart the user-service application and refresh http://localhost:8080/swagger-ui/index.html. The header now displays the customized title, description, developer contact link, email, and license information.
5. Replicating Swagger Configuration for the Device Service
To maintain consistency across our microservices architecture, we apply the exact same pattern to the device-service (running on port 8081).
- Add Dependency: Include
springdoc-openapi-starter-webmvc-uiindevice-service/pom.xml. - Create Configuration: Add an
OpenApiConfigclass indevice-servicecustomized for device management:
@Bean
public OpenAPI deviceServiceOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("Device Service API")
.description("Device service API documentation for managing home energy hardware")
.version("v1.0.0")
.contact(getContactInfo())
.license(getLicenseInfo()));
}
- Verify: Access
http://localhost:8081/swagger-ui/index.htmlto inspect device endpoints alongside DTO schemas (such asDeviceDTO).
6. Exposing Downstream Documentation Through the API Gateway
In a secure production microservices architecture, individual services reside within a private network and are not directly accessible from the outside world. External clients must communicate exclusively through the API Gateway (running on port 9000). Therefore, we must aggregate and expose all downstream documentation via the gateway.
Step 1: Update API Gateway pom.xml
Add the SpringDoc OpenAPI UI dependency to the API Gateway's pom.xml so it can render the Swagger UI interface at the entry point.
Step 2: Whitelist Documentation URLs in Security Filters
If your API Gateway uses security filters or excluded URL patterns (e.g., Spring Cloud Gateway or custom web filters), ensure that Swagger and OpenAPI paths are explicitly permitted.
Update application.properties in the API Gateway to exclude documentation endpoints:
# Excluded URLs for API Gateway security filters
gateway.excluded.urls=/swagger-ui.html,/swagger-ui/**,/v3/api-docs/**,/user-service/v3/api-docs,/device-service/v3/api-docs
Step 3: Configure Downstream Routes in Java
Create routing beans in the API Gateway configuration to proxy requests destined for documentation endpoints down to the respective backend services (localhost:8080 for user-service, localhost:8081 for device-service).
@Bean
public RouterFunction<ServerResponse> userServiceApiDocsRoute() {
return GatewayRouterFunctions.route("user_service_api_docs")
.route(RequestPredicates.path("/docs/user-service/v3/api-docs"),
HandlerFunctions.http("http://localhost:8080/v3/api-docs"))
.filter(setPathFilter("/v3/api-docs"))
.build();
}
@Bean
public RouterFunction<ServerResponse> deviceServiceApiDocsRoute() {
return GatewayRouterFunctions.route("device_service_api_docs")
.route(RequestPredicates.path("/docs/device-service/v3/api-docs"),
HandlerFunctions.http("http://localhost:8081/v3/api-docs"))
.filter(setPathFilter("/v3/api-docs"))
.build();
}
7. Merging Documentation Definitions in API Gateway Properties
To allow Swagger UI on the API Gateway (http://localhost:9000/swagger-ui/index.html) to switch between multiple microservice definitions (User Service and Device Service), configure grouped endpoints in application.properties:
# Swagger UI Grouped Definitions Configuration
springdoc.swagger-ui.urls[0].name=user-service
springdoc.swagger-ui.urls[0].url=/docs/user-service/v3/api-docs
springdoc.swagger-ui.urls[1].name=device-service
springdoc.swagger-ui.urls[1].url=/docs/device-service/v3/api-docs
8. Complete Flow Walkthrough: Accessing Docs via Gateway
Summary and Key Takeaways
- OpenAPI Specification vs. Swagger: OpenAPI is the vendor-neutral industry standard format describing REST APIs, while Swagger represents the suite of tools (like Swagger UI) used to implement and visualize that spec.
- Zero-Configuration Setup: Adding the
springdoc-openapi-starter-webmvc-uidependency automatically exposes/v3/api-docs(JSON) and/swagger-ui/index.html(UI) endpoints. - Custom Metadata: Use an
OpenAPI@Beaninside a@Configurationclass to customize API titles, descriptions, developer contact details, and licensing information. - Private Network Isolation: Microservices typically reside behind a private network boundary, making direct browser access impossible in production environments.
- API Gateway Aggregation: Route downstream service documentation through the API Gateway using custom router functions and proxy filters.
- Grouped UI Definitions: Configure
springdoc.swagger-ui.urlsproperties in the API Gateway to provide a unified dropdown menu allowing clients to toggle between multiple microservice documentations from a single portal. - Exercise Extension: Apply identical configuration steps to remaining ecosystem services (such as
injection-serviceanddevice-service) to ensure 100% API coverage.