title: Using Springfox to document jax-rs services in a Spring app
body: <p>I want to document the API of an existing app using Springfox. I added these dependencies to pom.xml:</p>
  
  <pre><code>&lt;dependency&gt;
      &lt;groupId&gt;io.springfox&lt;/groupId&gt;
      &lt;artifactId&gt;springfox-swagger2&lt;/artifactId&gt;
      &lt;version&gt;2.2.2&lt;/version&gt;
  &lt;/dependency&gt;
  
  &lt;dependency&gt;
      &lt;groupId&gt;io.springfox&lt;/groupId&gt;
      &lt;artifactId&gt;springfox-swagger-ui&lt;/artifactId&gt;
      &lt;version&gt;2.2.2&lt;/version&gt;
  &lt;/dependency&gt;
  </code></pre>
  
  <p>I've added the swagger package to the jersey packages in web.xml so that Swagger2Controller is picked up:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;!-- This web.xml file is not required when using Servlet 3.0 container, see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html#d4e194 --&gt;
  &lt;web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"&gt;
  
      &lt;context-param&gt;
          &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
          &lt;param-value&gt;classpath:application-context.xml&lt;/param-value&gt;
      &lt;/context-param&gt;
  
      &lt;listener&gt;
          &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
      &lt;/listener&gt;
  
      &lt;filter&gt;
          &lt;filter-name&gt;myapp&lt;/filter-name&gt;
          &lt;filter-class&gt;com.sun.jersey.spi.spring.container.servlet.SpringServlet&lt;/filter-class&gt;
          &lt;init-param&gt;
              &lt;param-name&gt;com.sun.jersey.config.property.packages&lt;/param-name&gt;
              &lt;param-value&gt;org.mystuff;springfox.documentation&lt;/param-value&gt;
          &lt;/init-param&gt;
          &lt;init-param&gt;
              &lt;param-name&gt;com.sun.jersey.config.property.JSPTemplatesBasePath&lt;/param-name&gt;
              &lt;param-value&gt;/WEB-INF/views&lt;/param-value&gt;
          &lt;/init-param&gt;
          &lt;init-param&gt;
              &lt;param-name&gt;com.sun.jersey.config.property.WebPageContentRegex&lt;/param-name&gt;
              &lt;param-value&gt;/(js|css|images|resources)/.*&lt;/param-value&gt;
          &lt;/init-param&gt;
          &lt;init-param&gt;
              &lt;param-name&gt;com.sun.jersey.config.feature.Redirect&lt;/param-name&gt;
              &lt;param-value&gt;true&lt;/param-value&gt;
          &lt;/init-param&gt;
          &lt;init-param&gt;
              &lt;param-name&gt;com.sun.jersey.config.feature.FilterForwardOn404&lt;/param-name&gt;
              &lt;param-value&gt;true&lt;/param-value&gt;
          &lt;/init-param&gt;
      &lt;/filter&gt;
  
      &lt;filter-mapping&gt;
          &lt;filter-name&gt;myapp&lt;/filter-name&gt;
          &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
      &lt;/filter-mapping&gt;
  &lt;/web-app&gt;
  </code></pre>
  
  <p>The application context specifies annotations for services, etc:</p>
  
  <pre><code>&lt;beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"&gt;
  
      &lt;context:property-placeholder ignore-unresolvable="true" location="classpath*:default.properties, classpath*:${runtime.environment}.properties" /&gt;
      &lt;context:annotation-config/&gt;
      &lt;context:component-scan base-package="org.myapp" use-default-filters="true" /&gt;
  
      &lt;aop:aspectj-autoproxy/&gt;
  &lt;/beans&gt;
  </code></pre>
  
  <p>The config class looks like:</p>
  
  <pre><code>@Configuration
  @EnableSwagger2
  public class ApiDocumentationConfiguration {
  
      @Bean
      public Docket documentation() {
          return new Docket(DocumentationType.SWAGGER_2)
                  .select()
                  .apis(RequestHandlerSelectors.any())
                  .paths(PathSelectors.regex("/api/.*"))
                  .build();
      }
  
      @Bean
      public UiConfiguration uiConfig() {
          return UiConfiguration.DEFAULT;
      }
  
      private ApiInfo metadata() {
          return new ApiInfoBuilder()
                  .title("My awesome API")
                  .description("Some description")
                  .version("1.0")
                  .contact("my-email@domain.org")
                  .build();
      }
  }
  </code></pre>
  
  <p>When started there's a stack trace:</p>
  
  <pre><code>org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'documentationPluginsBootstrapper' defined in URL [jar:file:/home/don/.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:/home/don/.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:/home/don/.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)
  ...
  Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webMvcRequestHandlerProvider' defined in URL [jar:file:/home/don/.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)
  ...
  Caused by: 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.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301)
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:999)
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
      at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813)
      at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
      ... 71 more
  </code></pre>
  
  <p>Is this the best approach to integrate Swagger? If so, what's the fix for the missing bean? Or is there a simpler approach?</p>
  
  <p>EDIT:</p>
  
  <p>Adding this to web.xml eliminates the stack trace:</p>
  
  <pre><code>&lt;bean id="requestMappingHandlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/&gt;
  </code></pre>
  
  <p>But a query to <a href="http://localhost:9090/myapp/v2/api-docs" rel="nofollow">http://localhost:9090/myapp/v2/api-docs</a> results in a 404, even though the startup console shows:</p>
  
  <pre><code>2015-09-28 21:54:16,689 INFO  [RequestMappingHandlerMapping] - Mapped "{[/v2/api-docs],methods=[GET]}" onto public org.springframework.http.ResponseEntity&lt;springfox.documentation.spring.web.json.Json&gt; springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation(java.lang.String)
  2015-09-28 21:54:16,690 INFO  [RequestMappingHandlerMapping] - Mapped "{[/configuration/ui]}" onto org.springframework.http.ResponseEntity&lt;springfox.documentation.swagger.web.UiConfiguration&gt; springfox.documentation.swagger.web.ApiResourceController.uiConfiguration()
  2015-09-28 21:54:16,690 INFO  [RequestMappingHandlerMapping] - Mapped "{[/configuration/security]}" onto org.springframework.http.ResponseEntity&lt;springfox.documentation.swagger.web.SecurityConfiguration&gt; springfox.documentation.swagger.web.ApiResourceController.securityConfiguration()
  2015-09-28 21:54:16,690 INFO  [RequestMappingHandlerMapping] - Mapped "{[/swagger-resources]}" onto org.springframework.http.ResponseEntity&lt;java.util.List&lt;springfox.documentation.swagger.web.SwaggerResource&gt;&gt; springfox.documentation.swagger.web.ApiResourceController.swaggerResources()
  </code></pre>
  
  <p>EDIT:</p>
  
  <p>It's possible to use jax-rs to map the SpringFox URIs, too:</p>
  
  <pre><code>&lt;context:component-scan base-package="springfox.documentation" use-default-filters="true" /&gt;
  
  ...
  
  @Autowired
  private Swagger2Controller swagger2Controller;
  
  ...
  
  @GET
  @Path("/v2/api-docs")
  public ResponseEntity&lt;Json&gt; apiDocs() {
      return swagger2Controller.getDocumentation(null);
  }
  </code></pre>
  
  <p>But this doesn't fill in the full context that SpringFox needs, so:</p>
  
  <pre><code>SEVERE: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
  java.lang.IllegalStateException: Could not find current request via RequestContextHolder. Is this being called from a Spring MVC handler?
      at org.springframework.util.Assert.state(Assert.java:385)
      at org.springframework.hateoas.mvc.ControllerLinkBuilder.getCurrentRequest(ControllerLinkBuilder.java:242)
      at org.springframework.hateoas.mvc.ControllerLinkBuilder.getBuilder(ControllerLinkBuilder.java:189)
      at org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo(ControllerLinkBuilder.java:85)
  </code></pre>