21

I'm trying to document and existing Rest API a Spring MVC project (NOT spring boot!).

My application is called api so http://localhost:9090/api would be the root endpoint. Because I'm using spring-data-rest, on that URL I can see the json of all my exposed repositories. So far so good.

I can also access the swagger JSON http://localhost:9090/api/v2/api-docs

The problem

I can't access the swagger-UI component on http://localhost:9090/api/swagger-ui.html . It gives me

WARN  org.springframework.web.servlet.PageNotFound- No mapping found for HTTP request with URI [/api/swagger-ui.html] in DispatcherServlet with name 'dispatcher'

Checking the spring logs when starting tomcat I can see something weird

DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory- Finished creating instance of bean 'swaggerApiListingReader'
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'swaggerConfig': no URL paths identified
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'swagger2Controller': no URL paths identified
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'swaggerMediaTypeReader': no URL paths identified
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'swaggerOperationModelsProvider': no URL paths identified
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'swaggerOperationResponseClassReader': no URL paths identified
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'swaggerOperationTagsReader': no URL paths identified
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'swaggerResponseMessageReader': no URL paths identified
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'swaggerParameterDescriptionReader': no URL paths identified
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'swaggerExpandedParameterBuilder': no URL paths identified
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'swaggerApiListingReader': no URL paths identified
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'swaggerProperties': no URL paths identified
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'springfox.documentation.swagger.configuration.SwaggerCommonConfiguration': no URL paths identified
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'springfox.documentation.swagger2.configuration.Swagger2DocumentationConfiguration': no URL paths identified
DEBUG org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping- Rejected bean name 'swagger2Module': no URL paths identified

That seems to indicate the for some reason swaggerController is not associated to any URL, hence the 404 error.

These are the version I'm working with

  <spring.version>4.2.8.RELEASE</spring.version>
  <spring-data.version>Gosling-SR4</spring-data.version>
  <spring-data-rest>2.4.6.RELEASE</spring-data-rest> 
   <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.6.1</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.6.1</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-data-rest</artifactId>
        <version>2.6.1</version>
    </dependency>

This is my Java conf. Worth pointing out that the method addResourceHandlers NEVER GETS executed

    @Configuration
    @EnableSwagger2
    @EnableWebMvc

  @Import({springfox.documentation.spring.data.rest.configuration.SpringDataRestConfiguration.class})
public class SwaggerConfig extends WebMvcConfigurerAdapter {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        System.out.println("******************************Configuring swagger resource handler");
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

Any suggestions? In short, swagger-ui does not work.

felipe
  • 1,039
  • 1
  • 13
  • 27

16 Answers16

30

This solution is courtesy this answer by @oksett

Create a configuration class, which extends WebMvcConfigurerAdapter and override the following methods:

If Using Spring 5, instead of extends WebMvcConfigurerAdapter implements WebMvcConfigurer

@Override
public void addViewControllers(ViewControllerRegistry registry) {
    registry.addRedirectViewController("/api/v2/api-docs", "/v2/api-docs");
    registry.addRedirectViewController("/api/swagger-resources/configuration/ui", "/swagger-resources/configuration/ui");
    registry.addRedirectViewController("/api/swagger-resources/configuration/security", "/swagger-resources/configuration/security");
    registry.addRedirectViewController("/api/swagger-resources", "/swagger-resources");
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/api/swagger-ui.html**").addResourceLocations("classpath:/META-INF/resources/swagger-ui.html");
    registry.addResourceHandler("/api/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}

In your case you need to add and implementation of addViewControllers to SwaggerConfig. Also note the changes in the addResourceHandlers method to prepend /api to the the rescue handler location.

You should now be able to access into my swagger-ui.html @ http://localhost:9090/api/swagger-ui.html

Swarit Agarwal
  • 2,520
  • 1
  • 26
  • 33
Dilip Krishnan
  • 5,417
  • 3
  • 37
  • 53
  • Thanks. No luck though. I can still see in spring logs BeanNameUrlHandlerMapping- Rejected bean ...: no URL paths identified for all swaggerBeans (swaggerConfig, swagger2Controller, swaggerMediaTypeReader, etc). Also the link from which you took the solution is **spring boot** . Any other idea? – felipe Apr 21 '17 at 15:10
  • The first thing I need to make sure is that the configuration actually executes when loading. Both *addViewControllers* and *addResourceHandlers* are never executed which I believe is the root cause.... – felipe Apr 21 '17 at 15:15
  • Its a spring mvc solution, boot is a super set. Secondly about the rejected bean, message, its a debug message so it might be a red-herring you're chasing. If it were significant you'd not see anything in the `/v2/apidocs` endpoint because one of the beans rejected is `swagger2Controller`. Another thing to try is to remove the @EnableWebMvc. – Dilip Krishnan Apr 21 '17 at 15:19
  • got you re spring boot and yeah it's DEBUG so it should not matter. What is the bit of configuration in Spring that triggers *addViewControllers* and * addResourceHandlers* ? That has not yet happened neither with my example or with your suggestion. – felipe Apr 21 '17 at 15:27
  • @filipe did this answer your question? – Dilip Krishnan Apr 25 '17 at 00:47
  • No Sr. Thanks for asking! The weirdest thing is that my colleague can access http://localhost:9090/api/swagger-ui.html with no problems...EXACTLY the same code base so I'm lost with this one. The only difference is that I'm running everything on a Mac and my colleague is in Linux so I'm now trying to run tomcat in a docker container (linux) and see what happens...if you do have any other suggestion please let us know. – felipe Apr 25 '17 at 14:38
20

The following is a complete code on how to configure spring boot with swagger doc and working UI.

pom.xml

<!-- Spring boot version is 2.0.3.RELEASE-->

<dependencies>
  <!-- Swagger 2 Doc Dependency -->
  <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger2</artifactId>
      <version>2.9.2</version>
  </dependency>

  <!-- Swagger 2 UI -->
  <dependency>
      <groupId>io.springfox</groupId>
      <artifactId>springfox-swagger-ui</artifactId>
      <version>2.9.2</version>
  </dependency>
</dependencies>

SwaggerDocConfig.java

package com.example.springbootswagger.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerDocConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry
                .addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry
                .addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    @Bean
    public Docket apiDocket() {

        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(getApiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.springbootswagger.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo getApiInfo() {

        return new ApiInfoBuilder()
                .title("Swagger API Doc")
                .description("More description about the API")
                .version("1.0.0")
                .build();
    }
}
biniam
  • 8,099
  • 9
  • 49
  • 58
15

Had a similar problem a while ago. I found out it was caused by @EnableWebMvc annotation in my custom Exception Handler.

@ControllerAdvice
@RestController
@EnableWebMvc
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {}

Removing @EnableWebMvc did the trick for me!!

8

This work for me

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");    
   }
}
hang gao
  • 421
  • 5
  • 6
3

In case of Spring Boot 2.x.x or Spring 5, implements WebMvcConfigurer in the Swagger class configuration and add the followed annotations : @Component, @Configuration, @EnableSwagger2. Look at the below implementation :

@Component
@Configuration
@EnableSwagger2
public class SwaggerConfig implements WebMvcConfigurer {
    @Bean
    public Docket api(){
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build()
                .apiInfo(getApiInfo());
    }

    private ApiInfo getApiInfo() {
        return new ApiInfoBuilder()
                .title("Custom Title")
                .description("Custom Description")
                .version("1.0.0")
                .build();
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

}

The swagger version 2.9.2 is the most compatible if you are using Spring 5 or Spring Boot 2.x.x

Maven dependecies :

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

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

Checkout the swagger doc on : http://localhost:8080/context-root/swagger-ui.html

Brahim SLIMANI
  • 310
  • 1
  • 8
3

I am using springfox open API 3 and this worked perfectly for me:

pom.xml

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>bootstrap</artifactId>
    <version>4.5.0</version>
</dependency>

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

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-oas</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-spring-web</artifactId>
            <version>3.0.0</version>
            
        </dependency>
        
        <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.2</version>
</dependency>

AppConfiguration

@Configuration
@EnableWebMvc
@ComponentScan("com.swagger.sample.test")
@EnableOpenApi
public class AppConfiguration {
    
    
}

ServletInitializer

public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
  @Override
  protected Class<?>[] getServletConfigClasses() {
    return new Class[] { AppConfiguration.class };
  }

  @Override
  protected String[] getServletMappings() {  
    return new String[] { "/" };
  }

  @Override
  protected Class<?>[] getRootConfigClasses() {
    return null;
  }

}

SpringConfig

@Component
public class SpringConfig implements WebMvcConfigurer {
    
    private static final Log LOGGER = LogFactory.getLog(ServletInitializer.class);

    
  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {       
      LOGGER.debug("[SpringConfig] addResourceHandlers");
        System.out.println("[SpringConfig] addResourcehandlers");
        registry. 
addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
.resourceChain(false);
  }

  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
              LOGGER.debug("[SpringConfig] addingViewControllers");
        System.out.println("[SpringConfig] addingViewControllers");
    registry.addViewController("/swagger-ui/")
        .setViewName("forward:" + "/swagger-ui/index.html");
  }
}

The resource path should point to the location of index.html in the jar see this image

mnagdev
  • 384
  • 3
  • 11
  • 1
    You don't really need dependecies: bootstrap, springfox-swagger2 (old version) and springfox-spring-web (which is transitive). – Aníbal Sep 20 '22 at 19:40
2

We ended up deploying Swagger-UI client separately and serving it through Nginx. We could not work out what's wrong with it and based on extensive research found many others having same difficulty so we decided to stop spending time on trying the embedded approach.

felipe
  • 1,039
  • 1
  • 13
  • 27
2

Had a similar problem and Dilips anwser worked. To be more precise:

  1. My api-docs location worked fine

  2. My swagger-ui.html was rendering but nothing viewed. In browser console i could see 404 for /configuration/ui dir.

the correct dir was /swagger-resources/configuration/ui so i had to do a redirection:

registry.addRedirectViewController("/configuration/ui", "/swagger-resources/configuration/ui");
Marcin
  • 195
  • 1
  • 7
2

I fixed the issue with this implementation:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.annotation.AuthenticationPrincipal;

import com.google.common.base.Predicates;

import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig extends WebSecurityConfigurerAdapter {
    public static String[] SWAGGER_URL_PATHS = new String[] { "/swagger-ui.html**", "/swagger-resources/**",
            "/v2/api-docs**", "/webjars/**" };

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.requestMatchers().antMatchers(SWAGGER_URL_PATHS).and().authorizeRequests().antMatchers(SWAGGER_URL_PATHS)
                .permitAll();
    }

    @Bean
    public Docket docket() {

        return new Docket(DocumentationType.SWAGGER_2).ignoredParameterTypes(AuthenticationPrincipal.class).select()
                .apis(Predicates.not(RequestHandlerSelectors.basePackage("org.springframework.boot")))
                .paths(PathSelectors.any()).build();
    }

}

P.S don't forget to this in your gradle file

compile('org.springframework.boot:spring-boot-starter-security')
m1sh0
  • 2,236
  • 1
  • 16
  • 21
1

The same thing happened to me, for me it worked to go from version 3.0.0 to 2.9.2

    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.9.2</version>
    </dependency>
    
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.9.2</version>
    </dependency>
David AJ
  • 29
  • 1
  • 4
1

If you are using spring web MVC even in spring boot ,If there is @EnableWebMvc in your project by any chance then remove it. For me this was creating the problem.

Vikash Kumar
  • 1,096
  • 11
  • 10
0

This is what works for me

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport{ 

@Override
public void addViewControllers(ViewControllerRegistry registry) {
  registry.addRedirectViewController("/configuration/ui", "/swagger-resources/configuration/ui");
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
    registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}}

Here is the pom:

   <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.9.2</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.9.2</version>
    </dependency>
vikifor
  • 3,426
  • 4
  • 45
  • 75
0

If you are using spring boot, that's all you need :

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.6.RELEASE</version>
    <relativePath />
</parent>



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

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

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

the configuration 4 swagger :

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any()).paths(PathSelectors.any()).build();
    }
}
Tiago Medici
  • 1,944
  • 22
  • 22
0

A new version of Swagger is available as of today's date: https://github.com/springfox/springfox

Better and easier configuration! I was upgrading Spring boot to 2.3.1 and adding swagger to my Microservices, was getting no mapping for the swaggger-ui.html after all proper configurations as mentioned in many of the answers above. Once I used this new version, all good!

EmeraldTablet
  • 812
  • 3
  • 12
  • 30
0

After few days of wondering I have finally found working answer, which should be correct for many maven problems - you just need to delete .m2/repository folder (it autorestores during 2 minutes) - and then you'll be able to update or downgrade any maven dependency, probably in this case they were swagger-ui and swagger2.

0

Changing
<version>3.0.0</version> to <version>2.9.1</version> Worked Fine For Me .

Spring Boot parent : 2.5.6

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version> 2.5.6</version>
    <relativePath/>
</parent>

Swagger Dependencies :

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

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