This document provides instructions for adding Swagger/OpenAPI documentation to all microservices in the Online Shopping System. Swagger provides interactive API documentation that allows developers to explore and test API endpoints.
- Interactive API Testing: Test endpoints directly from the browser
- Automatic Documentation: Generate docs from code annotations
- API Discovery: Easy exploration of available endpoints
- Client SDK Generation: Generate client libraries automatically
Add the following dependencies to each microservice's pom.xml:
<!-- Springdoc OpenAPI (Swagger) -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>Note: We're using
springdoc-openapiinstead of the olderspringfoxas it has better support for Spring Boot 3.x.
Location: /home/labuser/Downloads/Project_OSS/backend/user-auth-service/pom.xml
Add after existing dependencies:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>Location: /home/labuser/Downloads/Project_OSS/backend/product-service/pom.xml
Add after existing dependencies:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>Location: /home/labuser/Downloads/Project_OSS/backend/order-service/pom.xml
Add after existing dependencies:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>Location: /home/labuser/Downloads/Project_OSS/backend/payment-service/pom.xml
Add after existing dependencies:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>Add Swagger configuration to each service's application.properties:
# Swagger/OpenAPI Configuration
springdoc.api-docs.path=/api-docs
springdoc.swagger-ui.path=/swagger-ui.html
springdoc.swagger-ui.enabled=true
springdoc.swagger-ui.operationsSorter=method
springdoc.swagger-ui.tagsSorter=alpha
springdoc.show-actuator=falseCreate a configuration class for each service to customize the API documentation.
Create file: backend/user-auth-service/src/main/java/com/oss/auth/config/OpenApiConfig.java
package com.oss.auth.config;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI userAuthServiceAPI() {
return new OpenAPI()
.info(new Info()
.title("User Auth Service API")
.description("Authentication and User Management Service for Online Shopping System")
.version("1.0.0")
.contact(new Contact()
.name("Development Team")
.email("dev@onlineshopping.com"))
.license(new License()
.name("Apache 2.0")
.url("https://www.apache.org/licenses/LICENSE-2.0")))
.servers(List.of(
new Server().url("http://localhost:9090").description("Local Development"),
new Server().url("http://localhost:8181").description("API Gateway")))
.components(new Components()
.addSecuritySchemes("bearer-jwt", new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
.description("JWT token authentication")))
.addSecurityItem(new SecurityRequirement().addList("bearer-jwt"));
}
}Create file: backend/product-service/src/main/java/com/oss/product/config/OpenApiConfig.java
package com.oss.product.config;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI productServiceAPI() {
return new OpenAPI()
.info(new Info()
.title("Product Service API")
.description("Product Catalog and Inventory Management Service")
.version("1.0.0")
.contact(new Contact()
.name("Development Team")
.email("dev@onlineshopping.com")))
.servers(List.of(
new Server().url("http://localhost:8083").description("Local Development"),
new Server().url("http://localhost:8181").description("API Gateway")));
}
}Create file: backend/order-service/src/main/java/com/oss/order/config/OpenApiConfig.java
package com.oss.order.config;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI orderServiceAPI() {
return new OpenAPI()
.info(new Info()
.title("Order Service API")
.description("Order and Shopping Cart Management Service")
.version("1.0.0")
.contact(new Contact()
.name("Development Team")
.email("dev@onlineshopping.com")))
.servers(List.of(
new Server().url("http://localhost:8084").description("Local Development"),
new Server().url("http://localhost:8181").description("API Gateway")))
.components(new Components()
.addSecuritySchemes("bearer-jwt", new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")))
.addSecurityItem(new SecurityRequirement().addList("bearer-jwt"));
}
}Create file: backend/payment-service/src/main/java/com/oss/payment/config/OpenApiConfig.java
package com.oss.payment.config;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI paymentServiceAPI() {
return new OpenAPI()
.info(new Info()
.title("Payment Service API")
.description("Payment Processing and Coupon Management Service")
.version("1.0.0")
.contact(new Contact()
.name("Development Team")
.email("dev@onlineshopping.com")))
.servers(List.of(
new Server().url("http://localhost:8085").description("Local Development"),
new Server().url("http://localhost:8181").description("API Gateway")))
.components(new Components()
.addSecuritySchemes("bearer-jwt", new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")))
.addSecurityItem(new SecurityRequirement().addList("bearer-jwt"));
}
}Add Swagger annotations to your controllers for better documentation.
package com.oss.product.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/products")
@Tag(name = "Product Management", description = "APIs for managing products in the catalog")
public class ProductController {
@Operation(
summary = "Get all products",
description = "Retrieve a list of all products in the catalog"
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Successfully retrieved products",
content = @Content(schema = @Schema(implementation = ProductDTO.class))
)
})
@GetMapping
public List<ProductDTO> getAllProducts() {
// Implementation
}
@Operation(
summary = "Get product by ID",
description = "Retrieve a specific product by its ID"
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Product found",
content = @Content(schema = @Schema(implementation = ProductDTO.class))
),
@ApiResponse(
responseCode = "404",
description = "Product not found"
)
})
@GetMapping("/{id}")
public ProductDTO getProductById(
@Parameter(description = "Product ID", required = true)
@PathVariable Long id
) {
// Implementation
}
@Operation(
summary = "Create new product",
description = "Create a new product (Admin only)"
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "201",
description = "Product created successfully"
),
@ApiResponse(
responseCode = "400",
description = "Invalid input"
),
@ApiResponse(
responseCode = "403",
description = "Forbidden - Admin access required"
)
})
@PostMapping
public ProductDTO createProduct(@RequestBody ProductDTO productDTO) {
// Implementation
}
}package com.oss.auth.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/auth")
@Tag(name = "Authentication", description = "User authentication and registration APIs")
public class AuthController {
@Operation(
summary = "User registration",
description = "Register a new user account"
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "User registered successfully",
content = @Content(schema = @Schema(implementation = AuthenticationResponse.class))
),
@ApiResponse(
responseCode = "409",
description = "Email already registered"
),
@ApiResponse(
responseCode = "400",
description = "Invalid input data"
)
})
@PostMapping("/register")
public AuthenticationResponse register(@RequestBody RegisterRequest request) {
// Implementation
}
@Operation(
summary = "User login",
description = "Authenticate user and receive JWT token"
)
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Login successful",
content = @Content(schema = @Schema(implementation = AuthenticationResponse.class))
),
@ApiResponse(
responseCode = "401",
description = "Invalid credentials"
)
})
@PostMapping("/login")
public AuthenticationResponse login(@RequestBody LoginRequest request) {
// Implementation
}
}Add schema annotations to DTOs for better API documentation.
package com.oss.product.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import java.math.BigDecimal;
@Schema(description = "Product Data Transfer Object")
public class ProductDTO {
@Schema(description = "Product ID", example = "1", accessMode = Schema.AccessMode.READ_ONLY)
private Long id;
@Schema(description = "Product name", example = "Laptop", required = true)
private String name;
@Schema(description = "Product description", example = "High-performance laptop")
private String description;
@Schema(description = "Product price", example = "999.99", required = true)
private BigDecimal price;
@Schema(description = "Product category", example = "Electronics")
private String category;
@Schema(description = "Available stock quantity", example = "50")
private Integer stockQuantity;
@Schema(description = "Product image URL", example = "http://localhost:8181/api/products/1/image")
private String mainImageUrl;
@Schema(description = "Product rating", example = "4.5")
private Double rating;
@Schema(description = "Is product popular", example = "true")
private Boolean isPopular;
// Getters and setters
}After implementing Swagger, each service will have its own documentation available at:
| Service | Swagger UI URL | OpenAPI JSON |
|---|---|---|
| User Auth Service | http://localhost:9090/swagger-ui.html | http://localhost:9090/api-docs |
| Product Service | http://localhost:8083/swagger-ui.html | http://localhost:8083/api-docs |
| Order Service | http://localhost:8084/swagger-ui.html | http://localhost:8084/api-docs |
| Payment Service | http://localhost:8085/swagger-ui.html | http://localhost:8085/api-docs |
For production use, access through API Gateway:
| Service | Gateway Swagger UI URL |
|---|---|
| User Auth Service | http://localhost:8181/auth/swagger-ui.html |
| Product Service | http://localhost:8181/products/swagger-ui.html |
| Order Service | http://localhost:8181/orders/swagger-ui.html |
| Payment Service | http://localhost:8181/payments/swagger-ui.html |
Note: API Gateway routing configuration may need to be updated to properly route Swagger UI requests.
For endpoints requiring authentication:
- Login via
/auth/loginendpoint - Copy JWT token from the response
- Click "Authorize" button in Swagger UI
- Enter:
Bearer {your-jwt-token} - Click "Authorize" to apply
- Test protected endpoints
- Use Descriptive Summaries: Clearly describe what each endpoint does
- Include Examples: Provide example values for parameters and responses
- Document Error Codes: List all possible HTTP status codes
- Group Related Endpoints: Use
@Tagto organize endpoints - Mark Required Fields: Use
required = truefor mandatory parameters - Hide Internal Endpoints: Use
@Hiddenannotation for internal APIs
// Exclude Swagger endpoints from security
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers(
"/swagger-ui/**",
"/api-docs/**",
"/swagger-ui.html"
).permitAll()
.anyRequest().authenticated()
);
return http.build();
}
}For production environments, consider:
- Disable Swagger UI: Set
springdoc.swagger-ui.enabled=false - Restrict Access: Require authentication for API docs
- Use API Keys: Implement API key authentication
- Rate Limiting: Apply rate limits to documentation endpoints
- CORS Configuration: Properly configure CORS for Swagger UI
# Production Configuration
springdoc.swagger-ui.enabled=false
springdoc.api-docs.enabled=falseAdd Springdoc OpenAPI dependency to all service pom.xml files.
Create OpenApiConfig.java in each service's config package.
Add Swagger configuration to application.properties.
Add @Tag, @Operation, and @ApiResponse annotations to controllers.
Add @Schema annotations to DTO classes.
Permit access to Swagger endpoints in security configuration.
cd backend
mvn clean install
bash ../start_all.shVisit each service's Swagger UI URL and verify documentation is displayed correctly.
- API Overview: List of all endpoints grouped by tags
- Endpoint Details: Method, path, parameters, request body
- Try It Out: Interactive testing of endpoints
- Schemas: Model definitions with field descriptions
- Authentication: JWT token input for secured endpoints
- Responses: Example responses with status codes
Issue: Swagger UI not loading
- Solution: Check if dependency is correctly added and service is running
Issue: Endpoints not showing
- Solution: Verify controller package is scanned by Spring Boot
Issue: JWT authentication not working
- Solution: Ensure security configuration permits Swagger endpoints
Issue: 404 on /swagger-ui.html
- Solution: Try /swagger-ui/index.html (newer versions)
- Springdoc OpenAPI Documentation: https://springdoc.org/
- OpenAPI Specification: https://swagger.io/specification/
- Swagger UI: https://swagger.io/tools/swagger-ui/
Document Version: 1.0
Last Updated: December 26, 2025
Maintained By: Development Team
Note: This is a configuration guide. Actual implementation requires adding dependencies, creating configuration files, and annotating controllers as described above.