Naveen Chandra
Naveen Chandra

Reputation: 291

Unable to bring up swagger-ui from spring-boot application

I have a spring boot application that i am running using embedded tomcat server. I am partially successful in getting springfox-swagger integrated with the app. If i do a /v2/api-docs , i am able to see all the documentation of all the api's in the webapp. However, when i am trying to access the same from UI, it does not work. Below are the detailed results.

Output of - localhost:8080/api/swagger-resources

[ {
  "name" : "default",
  "location" : "/v2/api-docs",
  "swaggerVersion" : "2.0"
} ]

Output of - localhost:8080/api/v2/api-docs

I get valid results. I can confirm that and the output is too large to paste here

But when i try to access the swagger-ui, it does not work. Below are the different URL's i invoked to access the swagger-ui.

http://localhost:8080/swagger-ui.html - UI is loading, but no documentation of API's is present
http://localhost:8080/api/swagger-ui.html  - 404 Not Found
http://localhost:8080/springfox - 404 Not Found
http://localhost:8080/api/springfox - 404 Not Found

Below is my SwaggerConfig.java class

package com.vmware.vrack.lcm;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.swagger.web.UiConfiguration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import static springfox.documentation.builders.PathSelectors.regex;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(regex("/.*"))
                .build()
                .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        ApiInfo apiInfo = new ApiInfo(
                "My Project's REST API",
                "This is a description of your API.",
                "version-1",
                "API TOS",
                "[email protected]",
                "API License",
                "API License URL"
        );
        return apiInfo;
    }

}

Below are the swagger dependencies i am using

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

Below is the message converter webconfig file

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(jackson2Converter());
    }

    @Bean
    public MappingJackson2HttpMessageConverter jackson2Converter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(objectMapper());
        return converter;
    }

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        return objectMapper;
    }
}

The below link says that @EnableWebMvc should not be used in a spring-boot webapp and using the annotation might cause issues in bringing swagger-ui up. But, if i do not use the annotation, the web-app is not coming up (i have pasted the error stack trace below)

http://springfox.github.io/springfox/docs/current/#configuring-the-objectmapper

Error trace when i don't use the @EnableWebMvc Annotation

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'documentationPluginsBootstrapper' defined in URL [jar:file:/Users/ngorijala/.m2/repository/io/springfox/springfox-spring-web/2.2.2/springfox-spring-web-2.2.2.jar!/springfox/documentation/spring/web/plugins/DocumentationPluginsBootstrapper.class]: Unsatisfied dependency expressed through constructor argument with index 1 of type [springfox.documentation.spi.service.RequestHandlerProvider]: : Error creating bean with name 'webMvcRequestHandlerProvider' defined in URL [jar:file:/Users/ngorijala/.m2/repository/io/springfox/springfox-spring-web/2.2.2/springfox-spring-web-2.2.2.jar!/springfox/documentation/spring/web/plugins/WebMvcRequestHandlerProvider.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.util.List]: : No qualifying bean of type [org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping] found for dependency [collection of org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping] found for dependency [collection of org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webMvcRequestHandlerProvider' defined in URL [jar:file:/Users/ngorijala/.m2/repository/io/springfox/springfox-spring-web/2.2.2/springfox-spring-web-2.2.2.jar!/springfox/documentation/spring/web/plugins/WebMvcRequestHandlerProvider.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.util.List]: : No qualifying bean of type [org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping] found for dependency [collection of org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping] found for dependency [collection of org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1139)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1042)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized(ContextHandler.java:799)
    at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:499)
    at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:790)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:337)
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1343)
    at org.eclipse.jetty.maven.plugin.JettyWebAppContext.startWebapp(JettyWebAppContext.java:296)
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1336)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:742)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:499)
    at org.eclipse.jetty.maven.plugin.JettyWebAppContext.doStart(JettyWebAppContext.java:365)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:163)

I have a feeling that i am missing something trivial. Can someone please take a look and let me know what i am missing.?? Thanks in advance.!!

Upvotes: 26

Views: 45069

Answers (6)

Manish Kumar
Manish Kumar

Reputation: 23

For me the Issue was with the versions of Swagger API and Spring Boot Framework. I was using the Spring Boot latest version 2.6.0 with Swagger 3.0.0

I switched to Spring Boot 2.4.0 in my Parent Version. Even if you have devtools in ur project please do one manual maven update project and then run it.

hit the URL : your-base-url/swagger-ui/

Upvotes: 0

Bahgat Mashaly
Bahgat Mashaly

Reputation: 510

I have encountered this problem before and the problem was in the below line in application.properties:

spring.resources.add-mappings=false

Remove it or change its value to true.

Upvotes: 5

peps
peps

Reputation: 105

In my case I removed spring.resources.static-locations in properties file and it works.

Upvotes: 0

VIrtual Host
VIrtual Host

Reputation: 109

It worked for me, when i dint override the static path pattern.

In spring boot application just avoid "spring.mvc.static-path-pattern" from properties file and swagger-ui will works fine.

Upvotes: 1

maruf571
maruf571

Reputation: 1945

If you want to keep @EnableWebMvc annotation any way, you have to add the following

  @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/");

    }

Upvotes: 28

Dilip Krishnan
Dilip Krishnan

Reputation: 5487

springfox-swagger-ui is a web jar and requires that you set up resource handlers to inform the dispatch servlet how and which resource to serve up when you ask for ../swagger-ui.html. Usually in a spring-boot application auto-configuration takes care of setting it up for you. The reason its not loading in your case is because you've signaled to spring-boot that the application is going to be manually configured via the WebMvcConfigurerAdapter/@EnableWebMvc combination.

You should be able to place the @SpringBootApplication annotation on your main spring configuration and get rid of the WebConfig class all-together.

Since your WebConfig isn't adding any value other than making sure the JSON is indented, I'd suggest removing it all-together and replacing it with a Jackson2ObjectMapperBuilder bean instead.

For examples on how to do the same thing in spring-mvc/spring-boot etc. take a look at the springfox-demos project. In particular take a look at SpringConfig to see how to manually configure the resource handlers.

Upvotes: 19

Related Questions