Unable to bring up swagger-ui from spring-boot application
Asked Answered
E

6

25

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.!!

Empennage answered 25/8, 2015 at 1:35 Comment(0)
M
28

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

    }
Menzies answered 26/5, 2016 at 5:36 Comment(3)
+1 for solving my problem. Thank you. Also note that this method goes inside of the class that extends WebMvcConfigurerAdapter.Marcellus
While adding these values, make sure that you copy paste them from here because if you miss the "/" at the end, you will get 404 error.Prothrombin
Error:(108, -1) method does not override or implement a method from a supertypePopper
P
19

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.

Puri answered 27/8, 2015 at 1:28 Comment(1)
removed @EnableWebMvc and /swagger-ui.html is available. Thanks!Defeasible
H
5

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.

Hunch answered 28/9, 2018 at 21:51 Comment(0)
P
1

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.

Poll answered 16/11, 2018 at 5:10 Comment(0)
H
0

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

Haldi answered 17/5, 2019 at 4:32 Comment(0)
C
0

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/

Ceresin answered 15/12, 2021 at 8:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.