Search code examples
javaspring-bootswaggerswagger-ui

Cannot open swagger 2 in Spring Boot 3 App


I created an example of Spring Boot 3 with usage of swagger 2.

After I ran the app, I tried to open swagger ui through this URL (http://localhost:8080/swagger-ui.html) but I got "Whitelabel Error Page" result.

Here is swagger config shown below

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2).select()
                .apis(RequestHandlerSelectors.basePackage("com.deprem"))
                .paths(PathSelectors.regex("/.*"))
                .build().apiInfo(apiEndPointsInfo());

    }
    private ApiInfo apiEndPointsInfo() {
        return new ApiInfoBuilder().title("Title")
                .description("Description")
                .contact(new Contact("Name and Surname", "", ""))
                .license("Apache 2.0")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
                .version("1.0.0")
                .build();
    }
}

Here are dependencies used for swagger ui in pom.xml

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.10.2</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>3.0.0</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>3.0.0</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>


    </dependencies>

Here is the console output shown below.

Link

Here is the log info shown below

2023-02-09T01:08:16.232+03:00  INFO 24272 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2023-02-09T01:08:16.232+03:00 DEBUG 24272 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected StandardServletMultipartResolver
2023-02-09T01:08:16.232+03:00 DEBUG 24272 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected AcceptHeaderLocaleResolver
2023-02-09T01:08:16.232+03:00 DEBUG 24272 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected FixedThemeResolver
2023-02-09T01:08:16.233+03:00 DEBUG 24272 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@53b689a4
2023-02-09T01:08:16.233+03:00 DEBUG 24272 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Detected org.springframework.web.servlet.support.SessionFlashMapManager@609759ed
2023-02-09T01:08:16.233+03:00 DEBUG 24272 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
2023-02-09T01:08:16.233+03:00  INFO 24272 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
2023-02-09T01:08:16.239+03:00 DEBUG 24272 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : GET "/swagger-ui.html", parameters={}
2023-02-09T01:08:16.245+03:00 DEBUG 24272 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]]
2023-02-09T01:08:16.250+03:00 DEBUG 24272 --- [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler     : Resource not found
2023-02-09T01:08:16.250+03:00 DEBUG 24272 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed 404 NOT_FOUND
2023-02-09T01:08:16.254+03:00 DEBUG 24272 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : "ERROR" dispatch for GET "/error", parameters={}
2023-02-09T01:08:16.255+03:00 DEBUG 24272 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletResponse)
2023-02-09T01:08:16.276+03:00 DEBUG 24272 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, text/html;q=0.8]
2023-02-09T01:08:16.281+03:00 DEBUG 24272 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Exiting from "ERROR" dispatch, status 404

Here is my application.properties file shown below

spring.mvc.pathmatch.matching-strategy=ant_path_matcher

logging.level.org.springframework.web=DEBUG
logging.level.io.springfox=DEBUG

How can I fix the issue?

Here is my repo : Link


Solution

  • You need to use a different dependency for Spring Boot 3 and upgrade your Swagger logic to v3:

    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
        <version>2.0.2</version>
    </dependency>
    

    Example OpenAPI config:

    @Configuration
    public class OpenApiConfig {
    
        @Bean
        public OpenAPI openApi() {
            return new OpenAPI()
                .info(
                    new Info()
                        .title("App Title")
                        .description("App description")
                        .version("App version"));
                .externalDocs(
                    new ExternalDocumentation()
                        .description("Documentation name")
                        .url("https://example.com"));
        }
    
        @Bean
        public GroupedOpenApi categoryApi() {
            return GroupedOpenApi.builder()
                .group("Category API")
                .pathsToMatch("/categories/**")
                .build();
        }
    
        @Bean
        public GroupedOpenApi expenseApi() {
            return GroupedOpenApi.builder()
                .group("Expense API")
                .pathsToMatch("/expenses/**")
                .build();
        }
    
    }
    

    Example controller annotations:

    @RequestMapping("/categories")
    @RestController
    @Validated
    @ApiResponse(responseCode = "401", description = "Unauthorized, login required")
    @ApiResponse(responseCode = "500", description = "Internal server error, this should not happen")
    @Tag(name = "Category Controller", description = "Endpoint for retrieving and modifying categories")
    public class CategoryController {
    
        @GetMapping
        @Operation(
                summary = "Get all categories (paginated)",
                responses = @ApiResponse(responseCode = "200", description = "Category page returned"))
        public Page<CategoryDto> getCategories(@PageableDefault @ParameterObject Pageable pageable) {
            // Controller logic
        }
    
    }
    

    Example DTO:

    @Value
    public class CategoryDto {
    
        String id;
    
        @NotBlank
        @Size(max = 40, message = "must not exceed 40 characters")
        @Schema(maxLength = 40, required = true)
        String name;
    
        // Read-only attributes
    
        @Schema(accessMode = Schema.AccessMode.READ_ONLY)
        LocalDateTime createdAt;
    
        @Schema(accessMode = Schema.AccessMode.READ_ONLY)
        LocalDateTime lastModifiedAt;
    
    }