Swagger is a powerful tool for documenting and testing RESTful APIs. With Spring Boot 3, we can easily integrate Swagger using the OpenAPI specification. This tutorial will guide you through setting up Swagger in a Spring Boot 3 application and documenting a user management API.
Setting Up Swagger in Spring Boot 3
Spring Boot 3 supports OpenAPI through the springdoc-openapi-starter-webmvc-ui
dependency. To add Swagger to your project, include the following dependency in your pom.xml
file:
If you are using spring with spring-starter-web use this:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>{Choose the latest version}</version>
</dependency>
If you are using spring with spring-starter-webflux use this:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webflux-api</artifactId>
<version>{Choose the latest version}</version>
</dependency>
Once added, you can access the Swagger UI at http://localhost:8080/swagger-ui.html
when your application is running.
Swagger with Spring Security
If you are using spring security, modify the securityFilterChain to make the swagger-ui work.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
private JwtConfig jwtConfig;
public SecurityConfig(JwtConfig jwtConfig) {
this.jwtConfig = jwtConfig;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth.requestMatchers(HttpMethod.POST, "/user/register").permitAll()
.requestMatchers(HttpMethod.GET, "/swagger-ui/**").permitAll()
.requestMatchers(HttpMethod.GET, "/v3/**").permitAll()
.anyRequest().authenticated())
.oauth2ResourceServer(config -> config.jwt(jwt -> jwt.decoder(jwtConfig.jwtDecoder())));
return http.build();
}
}
- These endpoints are important because they load the ui from swagger.
- If you don't add them, you'll have 401(Unauthorized) and CSS errors.
.requestMatchers(HttpMethod.GET, "/swagger-ui/**").permitAll()
.requestMatchers(HttpMethod.GET, "/v3/**").permitAll()
Create a class of configurations
This is optional, but if you want to modify other things this class may be necessary.
package com.testcontainers.examples.configurations;
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;
@Configuration
public class SwaggerConfig {
@Bean
OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("Simple CRUD API")
.version("1.0")
.description("Documentation of the API using Swaager OpenAPI"));
}
}
User Management API with Swagger Annotations
Below is a Spring Boot 3 controller for managing users. It includes Swagger annotations to describe the API endpoints.
UserController.java
package com.testcontainers.examples.controllers;
import java.util.List;
import java.util.UUID;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.testcontainers.examples.dto.CreateUserDto;
import com.testcontainers.examples.dto.ErrorResponseDto;
import com.testcontainers.examples.models.UserModel;
import com.testcontainers.examples.services.UserService;
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;
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/")
public ResponseEntity<List<UserModel>> getAllUsers() {
return ResponseEntity.ok().body(userService.allUsers());
}
@GetMapping("/{id}")
@Operation(summary = "Find user by id", description = "Return 200 if the user exists.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "User found", content = @Content(mediaType = "application/json")),
@ApiResponse(responseCode = "400", description = "Wrong/not valid UUID", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponseDto.class))),
@ApiResponse(responseCode = "500", description = "default error", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponseDto.class)))
})
public ResponseEntity<UserModel> getUserById(@PathVariable String id) {
return ResponseEntity.ok().body(userService.findById(UUID.fromString(id)));
}
@DeleteMapping("/{id}")
@Operation(summary = "Delete user by id")
@ApiResponses({
@ApiResponse(responseCode = "204", description = "User deleted"),
@ApiResponse(responseCode = "400", description = "Wrong/not valid UUID", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponseDto.class))),
@ApiResponse(responseCode = "500", description = "default error", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponseDto.class)))
})
public ResponseEntity<?> deleteUserById(@PathVariable String id) {
userService.deleteById(UUID.fromString(id));
return ResponseEntity.noContent().build();
}
@PostMapping("/")
@Operation(summary = "Create a new user", description = "Return 201 if the user was successfully created.")
@ApiResponse(responseCode = "201", description = "User created successfully.")
public ResponseEntity<UserModel> createUser(@RequestBody CreateUserDto userInfo) {
var newUser = userService.save(userInfo);
return ResponseEntity.status(HttpStatus.CREATED).body(newUser);
}
}
Explanation of the Code
-
@RestController
and@RequestMapping("/users")
- Defines the controller and base path for user-related endpoints.
-
GET
/users/
- Returns a list of all users.
-
GET
/users/{id}
- Retrieves a user by ID.
- Uses
@Operation
and@ApiResponses
to document success (200) and error responses (400, 500).
-
DELETE
/users/{id}
- Deletes a user by ID.
- Returns
204 No Content
on success.
-
POST
/users/
- Creates a new user.
- Returns
201 Created
upon successful creation.
Running the Application
Once your Spring Boot application is running, you can access Swagger UI at http://localhost:8080/swagger-ui.html
Here, you can test your endpoints directly from the browser with a clean UI.
Conclusion
Integrating Swagger with Spring Boot 3 is straightforward with the springdoc-openapi
library. By using annotations like @Operation
and @ApiResponse
, you can create well-documented APIs that are easy to understand and use.
Top comments (0)