DEV Community

Cover image for Integrating Swagger with Spring Boot 3
Matheus Bernardes Spilari
Matheus Bernardes Spilari

Posted on

Integrating Swagger with Spring Boot 3

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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();
    }
}
Enter fullscreen mode Exit fullscreen mode
  • 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"));
    }
}

Enter fullscreen mode Exit fullscreen mode

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

Explanation of the Code

  1. @RestController and @RequestMapping("/users")

    • Defines the controller and base path for user-related endpoints.
  2. GET /users/

    • Returns a list of all users.
  3. GET /users/{id}

    • Retrieves a user by ID.
    • Uses @Operation and @ApiResponses to document success (200) and error responses (400, 500).
  4. DELETE /users/{id}

    • Deletes a user by ID.
    • Returns 204 No Content on success.
  5. 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.


📍 Reference

💻 Project Repository

👋 Talk to me

Top comments (0)