Replace #EnableSwagger2 after update to latest version - spring

I migrated to latest springfox-swagger2 version 2.10.0 but looks like #EnableSwagger2 is deprecated.
What annotation should I use in order to enable Swagger into Spring Boot project? #EnableSwagger2WebMvc?

#EnableSwagger2 was removed in swagger 2.10.x, but from 3.x.x it is there again.
#EnableSwagger2WebMvc is deprecated in 3.0.0+
Funny but true :)
Optionally you can use following dependency with Spring 5 MVC
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
and
remove explicit dependencies on springfox-swagger2
remove the #EnableSwagger2 annotations
add the springfox-boot-starter dependency
see: https://github.com/springfox/springfox

#Configuration
#EnableSwagger2WebMvc
#Import({SpringDataRestConfiguration.class, BeanValidatorPluginsConfiguration.class})
public class ApplicationSwaggerConfig {
#Bean
public Docket schoolApi() {
return new Docket(DocumentationType.SWAGGER_2).
select().
apis(RequestHandlerSelectors.basePackage("com.example.SampleProject")).
paths(PathSelectors.any()).
build();
}
For the other case pertaining to spring security checks, you can make your securityconfiguration class to extend WebsecurityConfigurerAdapter and then you can implement below method -
#Override public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers( "/v2/api-docs", "/swagger-resources/**", "/configuration/ui","/configuration/security", "/swagger-ui.html");
}
This should help I guess

Related

How to correctly handle "FeignException$ServiceUnavailableException" with fallback and without deprecated #EnableCircuitbreaker annotation

When using OpenFeign I implement fallbacks returning empty results so lists should simply appear as being empty. E.g. such as
#FeignClient(name = "objects", fallback = ObjectsClientFallback.class)
public interface ObjectsClient {
#RequestMapping("/objects/count")
Long count();
}
and
#Component
public class ObjectsClientFallback implements ObjectsClient {
#Override
public Long count() {
return 0L;
}
}
However, if the service is not started the application produces the ServiceUnavailableException when calling objectsClient.count() instead of using the fallback.
What is the correct way to use the fallback as #EnableCircuitBreaker has been deprecated recently? I do not want to add try-catch blocks if possible, especially in the context of lambdas or wrap this in service methods.
The application uses the #EnableDiscoveryClient annotation, like so
#SpringBootApplication
#EnableJpaRepositories
#EnableFeignClients
#EnableDiscoveryClient
#ServletComponentScan
public class Application {
//..
}
I've seen this question and checked the mentioned documentation, but it didn't help. Library versions are Spring-Boot 2.6.2 and Spring-Cloud 2021.0.0
Ended up using resilience4j for spring cloud.
Next to feign.circuitbreaker.enabled=true in application.properties which sets up a circuitbreaker with a default config.
One can add a custom configuration like this:
#Configuration
public class FeignConfiguration {
#Bean
public Customizer<Resilience4JCircuitBreakerFactory> circuitBreakerFactoryCustomizer() {
CircuitBreakerConfig circuitBreakerConfig =
CircuitBreakerConfig.custom()
.ignoreException(FeignException.ServiceUnavailable.class::isInstance)
.build();
return circuitBreakerFactory -> circuitBreakerFactory
.configure(builder -> builder.circuitBreakerConfig(circuitBreakerConfig),
ObjectsClient.class.getSimpleName());
}
}
Also, the resilience4j dependency needs to be in place, here a maven pom.xml is used.
<project>
<!-- .. -->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
</dependencies>
That way you can replace the deprecated hystrix implementation and remove the #EnableCircuitBreaker annotation.
In case you want a more fine-grained setup, here are is a discussion how to implement fallback with resilience4j via default methods.

SpringBoot application monitoring Adding Timed annotation cause to error

I'm implementing micrometer to spring web project. While trying to add #Timed annotation. Prior to add #Timed i'm supposed to create TimedSpect bean. But it says could not autowire no bean of MeterRegistry type found
#Configuration
public class MetricsCofiguration {
#Bean
public TimedAspect timedAspect(MeterRegistry registry) {
return new TimedAspect(registry);
}
}
Not sure if you still need this answer but this is what i tried and its working fine.
#Configuration
#EnableAspectJAutoProxy
public class TimedConfiguration {
#Autowired
MeterRegistry registry;
#Bean
public TimedAspect timedAspect(MeterRegistry registry) {
return new TimedAspect(registry);
}
}
Make sure you have below starter dependency in your pom.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Springfox swagger-ui.html unable to infer base URL - Caused by missing cookies

We have our Spring Boot services behind an API Gateway. With an earlier version of Springfox - 2.1.2 we had no issues in loading the swagger-ui.html page. This worked with Spring Boot 1.4.3.RELEASE. From then, we have upgraded to Boot 1.5.7 and upgraded Springfox to 2.8.0.
Now if we load the page we get an alert box with the following long message.
Unable to infer base url. This is common when using dynamic servlet
registration or when the API is behind an API Gateway. The base url is
the root of where all the swagger resources are served. For e.g. if
the api is available at http://example.org/api/v2/api-docs then the
base url is http://example.org/api/. Please enter the location
manually
I got some hints searching online, but it does not seem those situations apply to us. For one, if I simply revert back the versions, it starts working again through the same API Gateway.
Tracking the traffic, it seems calls to three XHR resources made by the .html page is causing issues. These are returning 401 from our API gateway. And the reason they return 401 is because the cookies are not passed along.
The three calls are:
https://base_address/base_context/swagger-resources/configuration/ui
https://base_address/base_context/swagger-resources/configuration/security
https://base_address/base_context/swagger-resources
If I load these URLs as pure browser requests - they work - because cookies are sent.
I doubt if CORS applies since the HTML is being served from the same address as the swagger JSON and actual service calls.
Any idea why this may be happening? Anybody faced similar issues? Suggestions for workaround? Thanks much in advance.
Add in the security config -- following URLS that are skipped for authentication ::
private static final String[] AUTH_WHITELIST = {
"/swagger-resources/**",
"/swagger-ui.html",
"/v2/api-docs",
"/webjars/**"
};
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(AUTH_WHITELIST);
}
Adding below annotation at the spring boot class resolved this issue for me.
#EnableSwagger2
I am using swagger version
<version>2.9.2</version>
SEE EDIT BELOW
Do you use spring security?
If yes, probably you skip some resources like this (right?):
"/swagger-resources/**",
"/swagger-ui.html",
"/v2/api-docs",
"/webjars/**"
Try to change it "/swagger-resources/**" to "**/swagger-resources/**".
My specific security config for swagger is:
private static final String[] AUTH_LIST = {
// -- swagger ui
"**/swagger-resources/**",
"/swagger-ui.html",
"/v2/api-docs",
"/webjars/**"
};
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers(AUTH_LIST).authenticated()
.and()
.httpBasic().authenticationEntryPoint(swaggerAuthenticationEntryPoint())
.and()
.csrf().disable();
}
#Bean
public BasicAuthenticationEntryPoint swaggerAuthenticationEntryPoint() {
BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();
entryPoint.setRealmName("Swagger Realm");
return entryPoint;
}
If you need/want I can send a sample project to GitHub to you know more about my security/swagger configs.
EDIT 2018/04/10
This problem is caused by a wrong version in springfox. See this issue on github to solve the problem.
To posterity:
In pom.xml
...
<repositories>
<repository>
<id>swagger</id>
<name>swagger</name>
<url>http://oss.jfrog.org/artifactory/oss-snapshot-local</url>
</repository>
</repositories>
...
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.1-SNAPSHOT</version>
</dependency>
...
Class that extends WebSecurityConfigAdapter:
#Configuration
public class WebSecurityConfigEntryPointApplication extends WebSecurityConfigurerAdapter {
private static final List<String> AUTH_LIST = Arrays.asList(
"/swagger-resources/**",
"/swagger-ui.html**",
"/webjars/**",
"favicon.ico");
#Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**").authorizeRequests().anyRequest().authenticated()
.and()
.exceptionHandling()
.defaultAuthenticationEntryPointFor(swaggerAuthenticationEntryPoint(), new CustomRequestMatcher(AUTH_LIST))
.and()
.httpBasic()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.csrf().disable();
}
#Bean
public BasicAuthenticationEntryPoint swaggerAuthenticationEntryPoint() {
BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();
entryPoint.setRealmName("Swagger Realm");
return entryPoint;
}
private class CustomRequestMatcher implements RequestMatcher {
private List<AntPathRequestMatcher> matchers;
private CustomRequestMatcher(List<String> matchers) {
this.matchers = matchers.stream().map(AntPathRequestMatcher::new).collect(Collectors.toList());
}
#Override
public boolean matches(HttpServletRequest request) {
return matchers.stream().anyMatch(a -> a.matches(request));
}
}
}
RestAuthenticationEntryPoint:
#Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
This happened to me, I was using SpringBoot 1.5.16 and Springfox 2.9.1.
In my application.properties, I had defined server.servlet-path=/api, but, somehow, the swagger-ui was ignoring the value defined. I've tried so many different way to make this work, and finally I found a workaround:
#Configuration
#EnableSwagger2
public class SwaggerConfiguration extends WebMvcConfigurationSupport {
#Bean
public Docket apiMonitoramento() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("REST API")
.description("Servicesx")
.build();
}
#Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
I was accessing http://localhost:8080/context/swagger-ui.html, but with that configuration the correct URL is: http://localhost:8080/context/api/swagger-ui.html
In my case, the cause of the problem was having:
#ComponentScan(basePackageClasses = {ApplicationRoot.class })
twice in two java files.
after removing the extra one, the problem went away.
Upgrade springfox-swagger2 and springfox-swagger-ui dependencies to 2.9.2 and also ensure the basePackage is given properly
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors
.basePackage("org.abc.xyz.controller"))
.paths(PathSelectors.regex("/.*"))
.build().apiInfo(apiEndPointsInfo());
I don't use spring security happened this question. My Project Use Maven Multiple Module, When access to the localhost:8080/swagger-ui.html happend this question, First I add #EnableSwagger2 in the SwaggerConf class ,Last I move #EnableSwagger to SpringBoot Application class ,this question is solved.
First:
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket api(){
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.zuoyan."))
.paths(PathSelectors.any())
.build();
}
}
Finally:
#SpringBootApplication(scanBasePackages = {"com.zuoyan.springboot.appmissionhall"})
#EnableSwagger2
public class ApplicationStartUpApplication {
public static void main(String[] args) {
SpringApplication.run(ApplicationStartUpApplication.class, args);
}
}
If you do not specify any special component scan options you will face this problem if you put the class with the #EnableSwagger2 annotation in a package that is not in the hierarchy of your Spring Boot Application class (#SpringBootApplication).
Assume your Spring Boot Application class in "de.oopexpert.app", then putting #EnableSwagger2 annotated class in ...
de.oopexpert.app will work
de.oopexpert.app.config will work
de.oopexpert.config will NOT work
You may adapt your component scan options by adding #ComponentScan(basePackages = {"de.oopexpert"}) to specify a different root of the hierarchy.
The solution from https://stackoverflow.com/a/56716898/13347514 by adding #EnableSwagger2WebMvc and #Import(SpringDataRestConfiguration.class) to the Main Application Class fixes my problem:
#SpringBootApplication
#EnableSwagger2WebMvc
#Import(SpringDataRestConfiguration.class)
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
In many cases it is due to Java Version incompatibility. Many times it doesn't work with Java 11, try using Java 8
Just clear your browser cache. It worked for me.
My Swagger Docket Bean Config file:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
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 DocketBean implements WebMvcConfigurer {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.swagger.demo"))
.paths(PathSelectors.any())
.build();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// enabling swagger-ui part for visual documentation
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
Swagger Dependencies in 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>
The swagger-ui url :
http://localhost:8080/swagger-ui.html
try with port 8080 - worked for me after i changed it to 8080
I added #EnableSwagger2WebMvc to the App class to fix it. I am using Spring boot 2.3.0.BUILD-SNAPSHOT and io.springfox 3.0.0-SNAPSHOT. SpringFoxConfig class stays the same.
package com.telixia.educare.academy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
#EnableSwagger2WebMvc
#SpringBootApplication
public class AcademyApplication {
public static void main(String[] args) {
SpringApplication.run(AcademyApplication.class, args);
}
}
This could also be caused by the springfox-swagger-ui and springfox-swagger2 versions mismatch in the pom.xml, for example, if you updated one but forgot to update another:
<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.9.2</version>
</dependency>
You need to make sure springfox-swagger-ui and springfox-swagger2 have the same version.
Firstly make sure these 2 dependencies are added and then annotate your main SpringBootApplication class with #EnableSwagger2 and then your problem will be solved.
<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>
I was facing the same issue with a basic Spring MVC application (no Spring Security).
I replaced
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.
addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
.resourceChain(false);
}
with
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.
addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("**/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
and it did the trick
In my case, adding the springfox-spring-webmvc dependency resolved the issue:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-spring-webmvc</artifactId>
<version>2.10.5</version>
</dependency>
I had the same problem, but just adding #EnableSwagger2 on top of the main App class fixed it.
example :
#SpringBootApplication
#EnableSwagger2
public class AcademyApplication {
public static void main(String[] args) {
SpringApplication.run(AcademyApplication.class, args);
}
#Configuration
class RestTemplateConfig {
#Bean
#LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
}
In my case, My project use Maven multiple module without spring security.
SpringBoot v2.2.7.RELEASE
Swagger2 & Swagger-ui v2.9.2
My solution is change the value of #Profile(), enter the right name of the configuration profile you create in the project resourse directory.
First:
#Configuration
#EnableSwagger2
#Profile({ "dev", "test" })
public class SwaggerConfig {
private ApiInfo getApiInfo(String title, String desc) {
return new ApiInfoBuilder().title(title)
.description(desc)
.version(DOC_VERSION)
.termsOfServiceUrl(URL)
.build();
}
}
Last:
#Configuration
#EnableSwagger2
// #Profile({ "dev", "test" })
#Profile({ "kf-oracle", "kf-mysql" })
public class SwaggerConfig {
private ApiInfo getApiInfo(String title, String desc) {
return new ApiInfoBuilder().title(title)
.description(desc)
.version(DOC_VERSION)
.termsOfServiceUrl(URL)
.build();
}
}
I had the same issue,i had written #EnableSwagger2 annotation at class level in SwaggerConfig file but i forgot to place #Configuration at class level in SwaggerConfig class. Adding that annotation solved my issue.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
#EnableSwagger2
#Configuration
public class swaggerConfig {
// swagger configuration
#Bean
public Docket productApi() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.basePackage("mention your package name here")).build();
}
}
If you have the same issue again then do #ComponentScan(basePackages = "mention your root package name here") in your Application.java file
First, add the Swagger dependency to pom.xml
Swagger Dependency in POM
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
After that, it's time to configure the Swagger 3rd party that we installed. Therefore follow the order below.
1/Make a package and set name Config
2/Make a class SwaggerConfig
3/After it set below code to that class
#Configuration
public class SwaggerConfig {
#Bean
public Docket SwaggerApi(){
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}
4/checked that class #Configuration and #Bean annotations
5/Need to enable Swagger2 in your main method class
6/use #EnableSwagger2 annotation to Enable Swagger 2
After that go to your browser and get swagger UI to see our UI. For it use this code http://localhost:8081/swagger-ui.html#/ check your server.port
If any doubt coming cheng your spring-boot-starter-parent pom.xml to low version.
Example:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
your project will run without error and smoothly.
Try the following in "*.yml" file
swagger:
enable: true
or try "swagger.enable=true" in "*.properties"
hi i found solution for this swagger popup as we can see a input box inside a swagger
you need to add /web or what ever url pattern configured in your code
example in popup input text field you need to add like this
popup with error
solution

Spring MVC Neo4jConfiguration class not found

I am learning Spring MVC. I want to extend the Neo4jConfiguration class but it is not available. I imported the following dependency:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
and after that I have reimported the libraries from maven. As I know I should now be able to extend the Neo4jConfiguration class. What is the problem? Thank you!
Neo4jConfiguration has been dropped from Spring Data Neo4j 4.2.
You can refer to the 'Configuring a Simple Spring Application' and 'Configuring Web Applications' in the Upgrading to Spring Data Neo4j 4.2 for a quick configuration without it.
The code sample they provide for simple configuration is:
#Configuration
#EnableNeo4jRepositories(basePackages = "org.neo4j.example.repository")
#EnableTransactionManagement
public class MyNeo4jConfiguration {
#Bean
public SessionFactory sessionFactory() {
// with domain entity base package(s)
return new SessionFactory("org.neo4j.example.domain");
}
#Bean
public Neo4jTransactionManager transactionManager() {
return new Neo4jTransactionManager(sessionFactory());
}
}

Spring boot & Swagger 2 UI & custom requestmappinghandlermapping - mapping issue

I have own RequestMappingHandlerMapping and I am using springfox-swagger-ui. After adding my custom mapping, I am not able to achieve swagger ui at http://localhost:8080/swagger-ui.html.
Any ideas?
This is my configuration.
#Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
#Override
#Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return new ApiVersionRequestMappingHandlerMapping("v");
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/webjars/**")
.addResourceLocations("(META-INF/resources/webjars");
}
}
Here's my pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
When you override WebMvcConfigurationSupport, you are also overriding spring Boot's mvc auto configuration (WebMvcAutoConfiguration). Therefore, resources that need spring boot's configuration will not work. This is not a problem specific to swagger.
You can find more info about this here:
https://github.com/spring-projects/spring-boot/issues/5004
As the github issue suggests, there will be changes on this in the future to make it easier. Currently there are some workarounds, as suggested there.
A quick and dirty way of doing this is by copying and pasting the WebMvcAutoConfiguration class into your own class, returning your own HandlerMapping from the requestMappingHandlerMapping() method of EnableWebMvcConfiguration and registering the copy of the WebMvcAutoConfiguration as an auto configuration class. You can see instructions here:
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html
Make sure you place your copy of the WebMvcAutoConfiguration at some package which is not component scanned and picked up automatically. It should just be registered as explained in the above link.
Also make sure you set the order of you custom HandlerMapping to 0 before returning it from the requestMappingHandlerMapping() method, like so:
#Bean
#Primary
#Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
// Must be #Primary for MvcUriComponentsBuilder to work
ApiVersionRequestMappingHandlerMapping handlerMapping = new ApiVersionRequestMappingHandlerMapping("v");
handlerMapping.setOrder(0);
handlerMapping.setInterceptors(getInterceptors());
handlerMapping.setContentNegotiationManager(mvcContentNegotiationManager());
PathMatchConfigurer configurer = getPathMatchConfigurer();
if (configurer.isUseSuffixPatternMatch() != null) {
handlerMapping.setUseSuffixPatternMatch(configurer.isUseSuffixPatternMatch());
}
if (configurer.isUseRegisteredSuffixPatternMatch() != null) {
handlerMapping.setUseRegisteredSuffixPatternMatch(configurer.isUseRegisteredSuffixPatternMatch());
}
if (configurer.isUseTrailingSlashMatch() != null) {
handlerMapping.setUseTrailingSlashMatch(configurer.isUseTrailingSlashMatch());
}
if (configurer.getPathMatcher() != null) {
handlerMapping.setPathMatcher(configurer.getPathMatcher());
}
if (configurer.getUrlPathHelper() != null) {
handlerMapping.setUrlPathHelper(configurer.getUrlPathHelper());
}
return handlerMapping;
}
It works for me.
Overriding addResourceHandlers instead of registering auto-configuration.
Github Source
#Configuration
#EnableWebMvc
#EnableSwagger2
public class WebConfig extends WebMvcConfigurerAdapter {
#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/");
}
}
Overriding requestMappingHandlerMapping() of WebMvcConfigurationSupport will turn off spring boot's auto configuration. For adding custom MVC Components you may use WebMvcRegistrations. Like, for providing custom RequestMappingHandlerMapping, We may override getRequestMappingHandlerMapping(), with custom RequestMappingHandlerMapping, ofWebMvcRegistrationsAdapter and provide it through webMvcRegistrationsHandlerMapping(). As,
#Configuration
class CustomRequestMappingHandlerMapping {
#Bean
public WebMvcRegistrationsAdapter webMvcRegistrationsHandlerMapping() {
return new WebMvcRegistrationsAdapter() {
#Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new ApiVersionRequestMappingHandlerMapping("v");
}
};
}
}
In Spring Boot 2.0.0, there is a simpler way to achieve this.
Create an instance of WebMvcRegistrations interface as a bean and override appropriate method to return the customized version of that object. Spring boot will read and use that instance.
In this case only the getRequestMappingHandlerMapping() needs to be overridden and a custom implementation returned
Above information is from a follow through based on the links provided by #Nazaret K.
More information at https://github.com/spring-projects/spring-boot/issues/5004
It can be solved by using WebMvcConfigurationSupport with adding resource handlers for swagger:
#Configuration
public class MvcConfiguration extends WebMvcConfigurationSupport {
#Value("${spring.application.name}")
private String applicationName;
//...irrelevant code here
#Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
I finally find it!
The right configuration is this:
#Configuration
public class VersioningMappingHandlerConfig {
#Bean
public ApiVersionRequestMappingHandlerMapping customMappingHandlerMapping() {
ApiVersionRequestMappingHandlerMapping handler = new ApiVersionRequestMappingHandlerMapping("v", 1, 1);
handler.setOrder(-1);
return handler;
}
}
Note: there is no extends WebMvcConfigurationSupport and bean name is customMappingHandlerMapping

Resources