Spring Boot not serving static content - spring

I can't get my Spring-boot project to serve static content.
I've placed a folder named static under src/main/resources. Inside it I have a folder named images. When I package the app and run it, it can't find the images I have put on that folder.
I've tried to put the static files in public, resources and META-INF/resources but nothing works.
If I jar -tvf app.jar I can see that the files are inside the jar on the right folder:
/static/images/head.png for example, but calling: http://localhost:8080/images/head.png, all I get is a 404
Any ideas why spring-boot is not finding this? (I'm using 1.1.4 BTW)

Not to raise the dead after more than a year, but all the previous answers miss some crucial points:
#EnableWebMvc on your class will disable org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration. That's fine if you want complete control but otherwise, it's a problem.
There's no need to write any code to add another location for static resources in addition to what is already provided. Looking at org.springframework.boot.autoconfigure.web.ResourceProperties from v1.3.0.RELEASE, I see a field staticLocations that can be configured in the application.properties. Here's a snippet from the source:
/**
* Locations of static resources. Defaults to classpath:[/META-INF/resources/,
* /resources/, /static/, /public/] plus context:/ (the root of the servlet context).
*/
private String[] staticLocations = RESOURCE_LOCATIONS;
As mentioned before, the request URL will be resolved relative to these locations. Thus src/main/resources/static/index.html will be served when the request URL is /index.html. The class that is responsible for resolving the path, as of Spring 4.1, is org.springframework.web.servlet.resource.PathResourceResolver.
Suffix pattern matching is enabled by default which means for a request URL /index.html, Spring is going to look for handlers corresponding to /index.html. This is an issue if the intention is to serve static content. To disable that, extend WebMvcConfigurerAdapter (but don't use #EnableWebMvc) and override configurePathMatch as shown below:
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
super.configurePathMatch(configurer);
configurer.setUseSuffixPatternMatch(false);
}
IMHO, the only way to have fewer bugs in your code is not to write code whenever possible. Use what is already provided, even if that takes some research, the return is worth it.
Edit July 2021:
WebMvcConfigurerAdapter has been deprecated since Spring 5. Implement WebMvcConfigurer and annotate with #Configuration.

Unlike what the spring-boot states, to get my spring-boot jar to serve the content:
I had to add specifically register my src/main/resources/static content through this config class:
#Configuration
public class StaticResourceConfiguration implements WebMvcConfigurer {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/" };
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
}
}

I had a similar problem, and it turned out that the simple solution was to have my configuration class extend WebMvcAutoConfiguration:
#Configuration
#EnableWebMvc
#ComponentScan
public class ServerConfiguration extends WebMvcAutoConfiguration{
}
I didn't need any other code to allow my static content to be served, however, I did put a directory called public under src/main/webapp and configured maven to point to src/main/webapp as a resource directory. This means that public is copied into target/classes, and is therefore on the classpath at runtime for spring-boot/tomcat to find.

Look for Controllers mapped to "/" or with no path mapped.
I had a problem like this, getting 405 errors, and banged my head hard for days. The problem turned out to be a #RestController annotated controller that I had forgot to annotate with a #RequestMapping annotation. I guess this mapped path defaulted to "/" and blocked the static content resource mapping.

The configuration could be made as follows:
#Configuration
#EnableWebMvc
public class WebMvcConfig extends WebMvcAutoConfigurationAdapter {
// specific project configuration
}
Important here is that your WebMvcConfig may override addResourceHandlers method and therefore you need to explicitly invoke super.addResourceHandlers(registry) (it is true that if you are satisfied with the default resource locations you don't need to override any method).
Another thing that needs to be commented here is that those default resource locations (/static, /public, /resources and /META-INF/resources) will be registered only if there isn't already a resource handler mapped to /**.
From this moment on, if you have an image on src/main/resources/static/images named image.jpg for instance, you can access it using the following URL: http://localhost:8080/images/image.jpg (being the server started on port 8080 and application deployed to root context).

I was having this exact problem, then realized that I had defined in my application.properties:
spring.resources.static-locations=file:/var/www/static
Which was overriding everything else I had tried. In my case, I wanted to keep both, so I just kept the property and added:
spring.resources.static-locations=file:/var/www/static,classpath:static
Which served files from src/main/resources/static as localhost:{port}/file.html.
None of the above worked for me because nobody mentioned this little property that could have easily been copied from online to serve a different purpose ;)
Hope it helps! Figured it would fit well in this long post of answers for people with this problem.

Did you check the Spring Boot reference docs?
By default Spring Boot will serve static content from a folder called /static (or /public or /resources or /META-INF/resources) in the classpath or from the root of the ServletContext.
You can also compare your project with the guide Serving Web Content with Spring MVC, or check out the source code of the spring-boot-sample-web-ui project.

I think the previous answers address the topic very well. However, I'd add that in one case when you have Spring Security enabled in your application, you might have to specifically tell Spring to permit requests to other static resource directories like for example "/static/fonts".
In my case I had "/static/css", "/static/js", "/static/images" permited by default , but /static/fonts/** was blocked by my Spring Security implementation.
Below is an example of how I fixed this.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.....
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/fonts/**").permitAll().
//other security configuration rules
}
.....
}

This solution works for me:
First, put a resources folder under webapp/WEB-INF, as follow structure
-- src
-- main
-- webapp
-- WEB-INF
-- resources
-- css
-- image
-- js
-- ...
Second, in spring config file
#Configuration
#EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter{
#Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
return resolver;
}
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resource/**").addResourceLocations("WEB-INF/resources/");
}
}
Then, you can access your resource content, such as
http://localhost:8080/resource/image/yourimage.jpg

Just to add yet another answer to an old question... People have mentioned the #EnableWebMvc will prevent WebMvcAutoConfiguration from loading, which is the code responsible for creating the static resource handlers. There are other conditions that will prevent WebMvcAutoConfiguration from loading as well. Clearest way to see this is to look at the source:
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java#L139-L141
In my case, I was including a library that had a class that was extending from WebMvcConfigurationSupport which is a condition that will prevent the autoconfiguration:
#ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
It's important to never extend from WebMvcConfigurationSupport. Instead, extend from WebMvcConfigurerAdapter.
UPDATE: The proper way to do this in 5.x is to implement WebMvcConfigurer

Put static resources under the directory:
/src/main/resources/static
add this property in application.properties file
server.servlet.context-path=/pdx
You can access from http://localhost:8080/pdx/images/image.jpg

There are 2 things to consider (Spring Boot v1.5.2.RELEASE)-
1) Check all Controller classes for #EnableWebMvc annotation, remove it if there is any
2) Check the Controller classes for which annotation is used - #RestController or #Controller. Do not mix Rest API and MVC behaviour in one class. For MVC use #Controller and for REST API use #RestController
Doing above 2 things resolved my issue. Now my spring boot is loading static resources with out any issues.
#Controller => load index.html => loads static files.
#Controller
public class WelcomeController {
// inject via application.properties
#Value("${welcome.message:Hello}")
private String message = "Hello World";
#RequestMapping("/")
public String home(Map<String, Object> model) {
model.put("message", this.message);
return "index";
}
}
index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>index</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet/less" th:href="#{/webapp/assets/theme.siberia.less}"/>
<!-- The app's logic -->
<script type="text/javascript" data-main="/webapp/app" th:src="#{/webapp/libs/require.js}"></script>
<script type="text/javascript">
require.config({
paths: { text:"/webapp/libs/text" }
});
</script>
<!-- Development only -->
<script type="text/javascript" th:src="#{/webapp/libs/less.min.js}"></script>
</head>
<body>
</body>
</html>

I'm using Spring Boot 2.2 and not getting any of my static content. I discovered two solutions that worked for me:
Option #1 - Stop using #EnableWebMvc annotation
This annotation disables some automatic configuration, including the part that automatically serves static content from commonly-used locations like /src/main/resources/static. If you don't really need #EnableWebMvc, then just remove it from your #Configuration class.
Option #2 - Implement WebMvcConfigurer in your #EnableWebMvc annotated class and implementaddResourceHandlers()
Do something like this:
#EnableWebMvc
#Configuration
public class SpringMVCConfiguration implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/static/js/");
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/static/css/");
registry.addResourceHandler("/vendor/**").addResourceLocations("classpath:/static/vendor/");
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
}
}
Just remember that your code is now in charge of managing all static resource paths.

In case the issue surfaces when launching the application from within an IDE (i.e. starting from Eclipse or IntelliJ Idea), and using Maven, the key to the solution is in the Spring-boot Getting Started documentation:
If you are using Maven, execute:
mvn package && java -jar target/gs-spring-boot-0.1.0.jar
The important part of which is adding the package goal to be run before the application is actually started. (Idea: Run menu, Edit Configrations..., Add, and there select Run Maven Goal, and specify the package goal in the field)

I was facing the same issue in spring boot 2.1.3 saying that resource not found 404. I removed below from applicatiion.properties.
#spring.resources.add-mappings=true
#spring.resources.static-locations=classpath:static
#spring.mvc.static-path-pattern=/**,
Removed #enableWebMVC and removed any WebMvcConfigurer overriding
//#EnableWebMvc
Also make sure you have #EnableAutoConfiguration in your config.
And put all static resources into src/main/resources/static and it just worked like magic finally..

I am using 1.3.5 and host a bunch of REST-services via Jersey implementation. That worked fine until I decided to add a couple of HTMLs + js files.
None of answers given on this forum helped me. However, when I added following dependency in my pom.xml all the content in src/main/resources/static was finally showing via browser:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<dependency>
It seems spring-web / spring-webmvc is the important transitive dependency that makes spring boot auto config turn on.

FYI: I also noticed I can mess up a perfectly working spring boot app and prevent it from serving contents from the static folder, if I add a bad rest controller like so
#RestController
public class BadController {
#RequestMapping(method= RequestMethod.POST)
public String someMethod(#RequestParam(value="date", required=false)String dateString, Model model){
return "foo";
}
}
In this example, after adding the bad controller to the project, when the browser asks for a file available in static folder, the error response is '405 Method Not Allowed'.
Notice paths are not mapped in the bad controller example.

using spring boot 2.*, i have a controller that maps to routes GetMapping({"/{var}", "/{var1}/{var2}", "/{var1}/{var2}/{var3}"}) and boom my app stop serving resources.
i know it is not advisable to have such routes but it all depends on the app you are building (in my case, i have no choice but to have such routes)
so here is my hack to make sure my app serve resources again. I simply have a controller that maps to my resources. since spring will match a direct route first before any that has variable, i decided to add a controller method that maps to /imgaes/{name} and repeated same for other resources
#GetMapping(value = "/images/{image}", produces = {MediaType.IMAGE_GIF_VALUE, MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE})
public #ResponseBody
byte[] getImage(#PathVariable String image) {
ClassPathResource file = new ClassPathResource("static/images/" + image);
byte[] bytes;
try {
bytes = StreamUtils.copyToByteArray(file.getInputStream());
} catch (IOException e) {
throw new ResourceNotFoundException("file not found: " + image);
}
return bytes;
}
and this solved my issue

Requests to /** are evaluated to static locations configured in
resourceProperties.
adding the following on application.properties, might be the only thing you need to do...
spring.resources.static-locations=classpath:/myresources/
this will overwrite default static locations, wich is:
ResourceProperties.CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
"classpath:/resources/", "classpath:/static/", "classpath:/public/" };
You might not want to do that and just make sure your resources end up in one of those default folders.
Performing a request:
If I would have example.html stored on /public/example.html
Then I can acces it like this:
<host>/<context-path?if you have one>/example.html
If I would want another uri like <host>/<context-path>/magico/* for files in classpath:/magicofiles/* you need a bit more config
#Configuration
class MyConfigClass implements WebMvcConfigurer
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/magico/**").addResourceLocations("/magicofiles/");
}

In my case I have a spring boot application which is kind of mixing spring and jaxrs. So I have a java class which inherits from the class org.glassfish.jersey.server.ResourceConfig. I had to add this line to the constructor of that class so that the spring endpoints are still called: property(ServletProperties.FILTER_FORWARD_ON_404, true).

Had the same problem, using gradle and eclipse and spent hours trying to figure it out.
No coding required, the trick is that you must use the menu option New->Source Folder (NOT New -> Folder) to create the static folder under src/main/resources. Don't know why this works, but did new -> source folder then i named the folder static (then source folder dialog gives an error for which you must check: Update exclusion filters in other source folders to solve nesting). The my new static folder I added index.html and now it works.

Well sometimes is worth to check did you override the global mappings by some rest controller. Simple example mistake (kotlin):
#RestController("/foo")
class TrainingController {
#PostMapping
fun bazz(#RequestBody newBody: CommandDto): CommandDto = return commandDto
}
In the above case you will get when you request for static resources:
{
title: "Method Not Allowed",
status: 405,
detail: "Request method 'GET' not supported",
path: "/index.html"
}
The reason for it could be that you wanted to map #PostMapping to /foo but forget about #RequestMapping annotation on the #RestController level. In this case all request are mapped to POST and you won't receive static content in this case.

Given resources under src/main/resources/static,
if you add this code, then all static content from src/main/resources/static will be available under "/":
#Configuration
public class StaticResourcesConfigurer implements WebMvcConfigurer {
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/static/");
}
}

In my case, some static files were not served, like .woff fonts and some images. But css and js worked just fine.
Update: A much better solution to make Spring Boot serve the woff fonts correctly is to configure the resource filtering mentioned in this answer, for example (note that you need both includes and excludes):
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>static/aui/fonts/**</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>static/aui/fonts/**</include>
</includes>
</resource>
</resources>
----- Old solution (working but will corrupt some fonts) -----
Another solution was to disable suffix pattern matching with setUseSuffixPatternMatch(false)
#Configuration
public class StaticResourceConfig implements WebMvcConfigurer {
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
// disable suffix matching to serve .woff, images, etc.
configurer.setUseSuffixPatternMatch(false);
}
}
Credits: #Abhiji did point me with 4. in the right direction!

Works for Thymeleaf, you can link the stylesheet using
<link th:href="#{/css/style.css}" rel="stylesheet" />

As said above, the file should be in $ClassPath/static/images/name.png, (/static or /public or /resources or /META-INF/resources). This $ClassPath means main/resources or main/java dir.
If your files are not in standard dirs, you can add the following configuration:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/lib/**"); // like this
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// ... etc.
}
...
}

Related

Spring Boot: Adding static resources from file system breaks existing mappings

I have a Spring Boot MVC application in which I am trying to load resources from an external folder on the file system. I have used the following to configure this:
#Configuration
#EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/where/**")
.addResourceLocations("file:///C:/some/where/");
}
...
}
Once I configure this, I can access my static files by going to http://serverurl/where/somefile
BUT, I am no longer able to access the home page at http://serverurl/
Any idea what I did wrong here?

How to tie annotations to spring properties?

In my Spring boot application I have around 30 controller classes. Each class has a #CrossOrigin annotation. When I work on it in eclipse it’s fine, but when I deploy to production I need to remove them.
So I was thinking to create a custom property in application.properties and somehow tie it to CrossOrigin annotations. So I can set property my-annotation=false and this will cancel the CrossOrigin annotations everywhere in the application. I tried looking into reflection but couldn’t figure out how to do it.
How can I make this work?
I'm afraid, spring doesn't work this way - once you've put an annotation its there for all controllers.
Technically this annotation is used somewhere deep inside in spring MVC (org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#initCorsConfiguration) so its not advisable to fiddle with it.
Probably it's possible to override the beans of this type by custom implementation and putting them into some configuration that will take place in production only and will not be loaded by default. But again, this is too "internal" solution.
Instead I suggest creating a global cors configuration outside the controller, so no #CrossOrigin annotation will stay in controllers.
So the first step would be defining a WebConfigurerAdapter:
#Configuration
class MyGlobalCorsConfiguration {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/greeting").allowedOrigins("http://localhost:9000");
}
};
}
}
The second step is to apply this configuration only upon some certain conditions:
It's possible to do with #ConditionalOnProperties annotation that can be put on the whole configuration or one single bean:
#ConditionalOnProperty(value = "myproject.cors.enabled", havingValue = "true",
matchIfMissing = false)
#Configuration
class MyGlobalCorsConfiguration {
....
}
Now during the third step you should put the property myproject.cors.enabled=true into the application properties that gets loaded only in production environment or something

What is the function of the #EnableWebFlux annotation

I have a very simple webflux demo application with freemarker which has got following files:
1.WebFluxDemoApplication.java
#SpringBootApplication
public class WebFluxDemoApplication {
public static void main(String[] args) {
SpringApplication.run(WebFluxDemoApplication.class, args);
}
#Controller
class HomeController {
#GetMapping("/hello")
public String hello() {
return "index";
}
}
}
2.index.ftl(located under classpath:/templates)
<html>
<head>
<title>demo</title>
</head>
<body></body>
</html>
3.application.yml(without any configuration)
4.pom.xml(with spring-boot-starter-freemarker and spring-boot-starter-webflux)
I can get normal page via http://localhost:8080/hello using these files, but if I add #EnableWebFlux to WebFluxDemoApplication, there's an error shows java.lang.IllegalStateException: Could not resolve view with name 'index'.
I notice that the Spring WebFlux's official guide states to use #EnableWebFlux to configure freemarker. Actually it works for template files, but there seems something wrong with static resources.
For example, I put a main.js file under classpath:/templates/js/, and add <script src="/js/main.js"></script> in index.ftl, then I get an error says WARN 3046 --- [ctor-http-nio-2] .a.w.r.e.DefaultErrorWebExceptionHandler : Failed to handle request [GET http://localhost:8080/js/main.js]: Response status 404 with reason "No matching handler"
UPDATE
For static resources problem, I found a solution which is to add a RouterFunction that resolves the static resources as the post stated.
As stated in the Spring Boot reference documentation, #EnableWebFlux will tell Spring Boot that you wish to take full control over the WebFlux configuration and disable all auto-configuration for this (including static resources).
#EnableWebFlux doesn't configure Freemarker, it actually sets up the whole WebFlux infrastructure. In the case of Spring Boot, adding the spring-boot-starter-freemarker as a dependency (and optionally configuring it through configuration properties) is all you need.

Changing default URL mapping for Serving Static Content in Spring Boot

My static resources stopped working as soon as I added a new Controller (non rest) in my application with the following mapping
#RequestMapping(value = "/{postId}/{postUri:.+}", method = RequestMethod.GET)
public String viewPost(#ModelAttribute("model") ModelMap model, PathVariable("postId") String postId, PathVariable("postUri") String postUri) {
// do something
}
After debugging I found that my newly added controller method started picking up static resources, basically, it has taken precedence over the default mapping for static resources.
For example, Request to the below static resource reaches my controller instead of static resource handler.
http://localhost:7999/css/bootstrap-2a31dca112f26923b51676cb764c58d5.css
I am using spring boot 1.4
Is there a way to modify the mapping URL for serving default static content since I do not want to modify the URL of my Controller method ?
Sure thing. There is a spring.mvc.static-path-pattern that you can use to override that:
spring.mvc.static-path-pattern=/resources/**
will map classpath:/static/css/foo.css to /resources/css/foo.css.
(I've made that clearer in a862b6d)
Having said that, I could only strongly recommend to change your path there. Having a path variable that catches the root context is really a bad idea.
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-static-content
By default Spring Boot will serve static content from a directory called /static (or /public or /resources or /META-INF/resources) in the classpath or from the root of the ServletContext. It uses the ResourceHttpRequestHandler from Spring MVC so you can modify that behavior by adding your own WebMvcConfigurerAdapter and overriding the addResourceHandlers method.
In a stand-alone web application the default servlet from the container is also enabled, and acts as a fallback, serving content from the root of the ServletContext if Spring decides not to handle it. Most of the time this will not happen (unless you modify the default MVC configuration) because Spring will always be able to handle requests through the DispatcherServlet.
By default, resources are mapped on /** but you can tune that via spring.mvc.static-path-pattern. For instance, relocating all resources to /resources/** can be achieved as follows:
spring.mvc.static-path-pattern=/resources/**
You can also customize the static resource locations using spring.resources.static-locations (replacing the default values with a list of directory locations). If you do this the default welcome page detection will switch to your custom locations, so if there is an index.html in any of your locations on startup, it will be the home page of the application.
In addition to the ‘standard’ static resource locations above, a special case is made for Webjars content. Any resources with a path in /webjars/** will be served from jar files if they are packaged in the Webjars format.
i dint use #EnableWebMVC. This worked for me and spring boot service server static content for default
localhost:8888/ and also for localhost:8888/some/path/
#Configuration
public static class WebServerStaticResourceConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/some/path/").setViewName("forward:/index.html");
}
}
I added spring.resources.static-location=file:../frontend/build in application.properties
index.html is present in the build folder
Use can also add absolute path
spring.resources.static-location=file:/User/XYZ/Desktop/frontend/build
For no controller pages:
#Controller
#RequestMapping("/feature")
public class DataTableController {
// map /feature/* to /feature/*
#RequestMapping(value="/{name}", method = RequestMethod.GET)
public ModelAndView staticPage(#PathVariable String name){
return new ModelAndView("feature/" + name);
}
}
For static resource except for HTML:
#EnableWebMvc
#Configuration
public class WebConfig implements WebMvcConfigurer {
// map /res/ to classpath:/resources/static/
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/res/**").addResourceLocations("classpath:/static/");
}
}

Spring Boot with Custom Converters breaks Swagger & how to move it

I have a very simple Spring Boot application. I launch this through the basic SpringApplication.run(Startup.class, args); and have a custom #Configuration class in there that overrides the default converters. I decided to add Swagger to the mix of things so that I can generate better documentation for our internal user base as there are gads of endpoints.
When I started things up, Swagger simply wouldn't work.
I decided to start a front-scratch Spring Boot with just one endpoint to document to see what went wrong. Out-of-the box this worked perfectly fine and I was able to get Swagger running via just hitting the http://localhost:8080/swagger-ui.html base URL.
When I implemented my custom #Configuration class that extended WebMvcConfigurationSupport, Swagger no longer worked.
My configuration overrode a single method:
#Configuration
public class StartupConfiguration extends WebMvcConfigurationSupport {
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(getJsonConverter());
}
}
That's it. I decided to add the default converters as well without any luck. Then I just emptied the class and left it as:
#Configuration
public class StartupConfiguration extends WebMvcConfigurationSupport {
}
Swagger is still broken - if I remove the class completely, then it works.
What can I do to keep my custom configuration data and run Swagger? I would also love to move it to something like http://localhost:8080/swagger/ rather than the default file it uses, but that is a completely separate issue for now.
My launch of Swagger looks like this:
#Configuration
#EnableSwagger2
public class SwaggerConfiguration {
#Bean
public Docket getDocket() {
// ...
return new Docket(DocumentationType.SWAGGER_2)
.groupName("Core API")
.apiInfo(infoBuilder.build())
.select().paths(PathSelectors.regex("/*"))
.build();
}
}
Overriding the default resource handler worked for me. I added the following to the configuration class extending WebMvcConfigurationSupport:
#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/");
}

Resources