I want to set the Logger for just the /health actuator endpoint to OFF in the application.properties file. Application is on Spring Boot 1.5.
The /health would be our new monitoring url for the F5. I don't want to flood the logs.
I have this.
logging.level.org.springframework.web=DEBUG
org.springframework.boot.actuate.health.Logger=OFF
logging.level.org.springframework.boot.actuate.health=OFF
I'm still getting DEBUG logging in the console and the log file. The only thing that works is setting the first one to INFO or higher. But, that is not desirable. So, right now i'm getting this
2020-05-06 17:14:01.545 DEBUG 58588 --- [nio-9095-exec-5] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/health]
2020-05-06 17:14:01.552 DEBUG 58588 --- [nio-9095-exec-5] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/health] is: -1
2020-05-06 17:14:01.848 DEBUG 58588 --- [nio-9095-exec-5] m.m.a.RequestResponseBodyMethodProcessor : Written [UP {}] as "application/vnd.spring-boot.actuator.v1+json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter#144409aa]
2020-05-06 17:14:01.849 DEBUG 58588 --- [nio-9095-exec-5] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2020-05-06 17:14:01.849 DEBUG 58588 --- [nio-9095-exec-5] o.s.web.servlet.DispatcherServlet : Successfully completed request
Do i need to set a different logger property? For a different class/package?
I use logback, so I added a logging filter for this. You need to change the regexes to match your own logging format.
package eu.stackoverflow.logging;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
public class IgnoringHealthAndPrometheusLoggingFilter extends Filter<ILoggingEvent> {
private static final Pattern HEALTH_OR_PROMETHEUS =
Pattern.compile("GET \"/(health|prometheus)\", parameters=\\{}");
private static final Pattern COMPLETED =
Pattern.compile("Completed 200 OK");
private Set<String> activeThreads = new HashSet<>();
#Override
public FilterReply decide(ILoggingEvent loggingEvent) {
if (isHealthOrPrometheus(loggingEvent.getMessage())) {
activeThreads.add(loggingEvent.getThreadName());
return FilterReply.DENY;
} else if (isCompleted200Ok(loggingEvent.getMessage()) && activeThreads.remove(loggingEvent.getThreadName())) {
return FilterReply.DENY;
} else {
return FilterReply.ACCEPT;
}
}
private boolean isHealthOrPrometheus(String message) {
return HEALTH_OR_PROMETHEUS.matcher(message).matches();
}
private boolean isCompleted200Ok(String message) {
return COMPLETED.matcher(message).matches();
}
}
<appender class="ch.qos.logback.core.ConsoleAppender" name="CONSOLE">
<filter class="eu.stackoverflow.logging.IgnoringHealthAndPrometheusLoggingFilter" />
</appender>
More info on logback filters: https://logback.qos.ch/manual/filters.html
Related
I am following a tutorial on Spring MVC and my project is not working as expected. I am using #ResponseBody to return a string message but it is throwing a whitelabel error page. I have scoured the Internet for last 2 days but still clueless about what could I possibly do wrong. Can anybody throw some light upon this?
Spring Framework boot : 2.5.4, Java version : 11
Code snippet for LoginController :
package com.in28minutes.springboot.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
public class LoginController {
#RequestMapping(value="/login", method=RequestMethod.GET, produces="text/plain")
#ResponseBody
public String loginMessage() {
return "Hello World";
}
}
2021-09-10 15:33:54.158 DEBUG 8556 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : GET "/login", parameters={}
2021-09-10 15:33:54.158 DEBUG 8556 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped to ResourceHttpRequestHandler [Classpath [META-INF/resources/], Classpath [resources/], Classpath [static/], Classpath [public/], ServletContext [/]]
2021-09-10 15:33:54.160 DEBUG 8556 --- [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler : Resource not found
2021-09-10 15:33:54.160 DEBUG 8556 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed 404 NOT_FOUND
2021-09-10 15:33:54.160 DEBUG 8556 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : "ERROR" dispatch for GET "/error", parameters={}
2021-09-10 15:33:54.161 DEBUG 8556 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletResponse)
2021-09-10 15:33:54.177 DEBUG 8556 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, text/html;q=0.8]
2021-09-10 15:33:54.178 DEBUG 8556 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Exiting from "ERROR" dispatch, status 404
#SpringBootApplication
public class SpringBootFirstWebApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootFirstWebApplication.class,
args);
}
}
I will guess that your SpringBootFirstWebApplication is not placed in the parent package of all other packages in your application and therefore #Controller annotation in LoginController is not scanned.
If that is the case, change SpringBootFirstWebApplication to the parent package of all other packages in your application.
It seems like your requested URL in #RequestMapping is wrong. Your expected URL is value="/home", but your actual is value="/login"
Background: I have traditional Spring MVC application (Spring Boot) that utilizes Spring Cloud OpenFeign (REST service consumption) and Apache CXF (SOAP service consumption). I'm trying to see if I can consolidate these two HTTP clients to just Spring's WebClient.
I'm trying to figure out if there is a better way to reference attributes placed in RequestContextHolder and then consume/use them in an ExchangeFilterFunction (replaces various Feign/CXF request interceptors).
For example, the following works:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.RouterFunctions;
import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.servlet.function.ServerResponse;
import java.util.HashMap;
import java.util.Map;
import static java.util.Objects.requireNonNull;
#SpringBootApplication
public class DemoApplication {
private static Log logger = LogFactory.getLog(DemoApplication.class);
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
RouterFunction<ServerResponse> router(WebClient.Builder webClientBuilder) {
WebClient webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").filter((req, next) -> {
Object foo = requireNonNull(RequestContextHolder.getRequestAttributes()).getAttribute("foo", WebRequest.SCOPE_REQUEST);
logger.info("Foo=" + foo);
return next.exchange(ClientRequest.from(req).header("foo", foo.toString()).build());
}).build();
return RouterFunctions.route()
.before((request) -> {
logger.info("Setting foo from " + Thread.currentThread().getName());
RequestContextHolder.getRequestAttributes().setAttribute("foo", "bar", WebRequest.SCOPE_REQUEST);
return ServerRequest.from(request).build();
})
.GET("/test", (request) -> {
ClientResponse response = webClient.get().uri("/todos/1").exchange().block();
Map<String, Object> body = new HashMap<>();
body.put("attributes", RequestContextHolder.getRequestAttributes().getAttributeNames(WebRequest.SCOPE_REQUEST));
body.put("todo", response.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {}).block());
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(body);
})
.build();
}
}
Please note the above is still a servlet/blocking application example. The only reactive part is WebClient and the ExchangeFilterFunction. RestTemplate is in maintenance mode and the recommendation is to use WebClient as per the javadoc
When I spam the endpoint with multiple requests, it seemingly works:
2020-08-24 21:26:22.829 INFO 15212 --- [nio-8080-exec-1] com.example.demo.DemoApplication : Setting foo from http-nio-8080-exec-1
2020-08-24 21:26:22.829 INFO 15212 --- [nio-8080-exec-1] com.example.demo.DemoApplication : Foo=bar
2020-08-24 21:26:22.915 INFO 15212 --- [nio-8080-exec-2] com.example.demo.DemoApplication : Setting foo from http-nio-8080-exec-2
2020-08-24 21:26:22.916 INFO 15212 --- [nio-8080-exec-2] com.example.demo.DemoApplication : Foo=bar
2020-08-24 21:26:23.011 INFO 15212 --- [nio-8080-exec-3] com.example.demo.DemoApplication : Setting foo from http-nio-8080-exec-3
2020-08-24 21:26:23.011 INFO 15212 --- [nio-8080-exec-3] com.example.demo.DemoApplication : Foo=bar
2020-08-24 21:26:23.118 INFO 15212 --- [nio-8080-exec-4] com.example.demo.DemoApplication : Setting foo from http-nio-8080-exec-4
2020-08-24 21:26:23.119 INFO 15212 --- [nio-8080-exec-4] com.example.demo.DemoApplication : Foo=bar
However this feels wrong to do since Reactor offers Context and even more so since this Reactor FAQ explicitly calls out the following (emphasis mine):
Now that we’ve established that MDC "just working" is not the best assumption to make in a declarative API
Any help/guidance is appreciated.
I've turned off the Logging for an actuator endpoint, but DispatcherServlet (and RequestReponseBodyMethodProcessor) still log the mapping and response.
How can i prevent this logging for just this one endpoint? I've already turned them off
management.logging.level.org.springframework.boot.actuate.health=OFF
logging.level.org.springframework.boot.actuate.health=OFF
org.springframework.boot.actuate.health.Logger=OFF
but it still comes like this:
2020-05-06 17:14:01.545 DEBUG 58588 --- [nio-9095-exec-5] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/health]
2020-05-06 17:14:01.552 DEBUG 58588 --- [nio-9095-exec-5] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/health] is: -1
2020-05-06 17:14:01.848 DEBUG 58588 --- [nio-9095-exec-5] m.m.a.RequestResponseBodyMethodProcessor : Written [UP {}] as "application/vnd.spring-boot.actuator.v1+json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter#144409aa]
2020-05-06 17:14:01.849 DEBUG 58588 --- [nio-9095-exec-5] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2020-05-06 17:14:01.849 DEBUG 58588 --- [nio-9095-exec-5] o.s.web.servlet.DispatcherServlet : Successfully completed request
Just set in application.properties log level to WARN
logging.level.org.springframework.web.servlet.DispatcherServlet=WARN
logging.level.org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor=WARN
please check if this solves the issue
In annotation SpringBootApplication add exclude DispatcherServletAutoConfiguration class in main class.
#SpringBootApplication(exclude = { DispatcherServletAutoConfiguration.class })
reference :
Switch off DispatcherServlet on Spring Boot
If your goal is logging all the incoming HTTP requests, the solution is not enabling DEBUG logging level in the DispatcherServlet.
You can define a bean of type:
org.springframework.web.filter.CommonsRequestLoggingFilter
and override the method:
org.springframework.web.filter.CommonsRequestLoggingFilter.shouldLog(HttpServletRequest)
So you can decide which requests are logged or not.
Obviously, you must set the logging level of the filter to DEBUG:
logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG
More info at Baeldubg site.
Just use the below in the .properties
logging.level.org.springframework.web=WARN
Sorry to necro a thread, but here's the answer I came up with:
Create a bean as below:
package com.package.your.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CommonsRequestLoggingFilter;
import javax.servlet.http.HttpServletRequest;
#Configuration
public class RequestLoggingFilterConfig {
#Bean
public CommonsRequestLoggingFilter logFilter() {
CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter() {
#Override
public void beforeRequest(HttpServletRequest request, String message) {
// Don't log any actuator endpoints
if (!request.getRequestURI().contains("actuator")) {
this.logger.debug(message);
}
}
#Override
public void afterRequest(HttpServletRequest request, String message) {
// Empty because it logs the same content as beforeRequest
}
};
filter.setBeforeMessagePrefix("");
filter.setBeforeMessageSuffix("");
filter.setIncludeClientInfo(true);
filter.setIncludeHeaders(true);
filter.setIncludePayload(true);
filter.setIncludeQueryString(true);
return filter;
}
}
Add the following to applications.properties instead of setting DispatcherServlet to debug:
logging.level.com.package.your.config.RequestLoggingFilterConfig=debug
This works beautifully as intended. Filtering is controlled by the if statement in the beforeRequest method.
I am writing a RESTful web services using spring boot. I am using jwt bearer token for authentication an authorisation.
Below is my RestController
#RestController("api/v1/users")
public class UserController {
#Autowired
UserService userService;
#PostMapping
public User saveUser(#RequestBody User user) {
return userService.saveUser(user);
}
#GetMapping
public List<User> getUsers(#RequestParam(required = false) String pageNumber, String pageSize, String role, String status) {
return userService.findAll(pageNumber, pageSize, role, status);
}
}
When I hit the api with request-url
http://localhost:8080/api/v1/users?pageNumber=0&pageSize=6&role=admin
Its work perfectly
but if I change the url endpoint to some invalid endpoint like
http://localhost:8080/api/v1/hhh?pageNumber=0&pageSize=6&role=admin
It still returning same results as per 1st correct endpoint.
Below are some logs statements from springframework debug logging
Checking match of request : '/api/v1/hhh'; against
'/api/test/secureTest'
2019-12-28 19:16:47.601 DEBUG 5591 --- [nio-8080-exec-5]
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request :
'/api/v1/hhh'; against 'api/authenticate'
2019-12-28 19:16:47.601 DEBUG 5591 --- [nio-8080-exec-5]
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request :
'/api/v1/hhh'; against '/api/v1/users/me'
2019-12-28 19:16:47.601 DEBUG 5591 --- [nio-8080-exec-5]
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request :
'/api/v1/hhh'; against '/api/v1/student'
2019-12-28 19:16:47.601 DEBUG 5591 --- [nio-8080-exec-5]
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request :
'/api/v1/hhh'; against '/api/v1/faculty'
2019-12-28 19:16:47.601 DEBUG 5591 --- [nio-8080-exec-5]
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request :
'/api/v1/hhh'; against '/api/v1/admin'
2019-12-28 19:16:47.601 DEBUG 5591 --- [nio-8080-exec-5]
o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request :
'/api/v1/hhh'; against '/api/v1/users'
2019-12-28 19:16:47.601 DEBUG 5591 --- [nio-8080-exec-5]
o.s.s.w.a.i.FilterSecurityInterceptor : Public object -
authentication not attempted
2019-12-28 19:16:47.601 DEBUG 5591 --- [nio-8080-exec-5]
o.s.security.web.FilterChainProxy :
/api/v1/hhh?pageNumber=0&pageSize=6&role=admin reached end of
additional filter chain; proceeding with original chain
2019-12-28 19:16:47.602 TRACE 5591 --- [nio-8080-exec-5]
o.s.web.servlet.DispatcherServlet : GET
"/api/v1/hhh?pageNumber=0&pageSize=6&role=admin", parameters={masked},
headers={masked} in DispatcherServlet 'dispatcherServlet'
2019-12-28 19:16:47.602 TRACE 5591 --- [nio-8080-exec-5]
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance
of singleton bean 'api/v1/users'
2019-12-28 19:16:47.602 TRACE 5591 --- [nio-8080-exec-5]
s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public
java.util.List
com.asset.app.user.UserController.getUsers(java.lang.String,java.lang.String,java.lang.String,java.lang.String)
2019-12-28 19:16:47.602 TRACE 5591 --- [nio-8080-exec-5]
.w.s.m.m.a.ServletInvocableHandlerMethod : Arguments: [0, 6, admin,
null]
I feel Spring cache the endpoint url and used if in case of no match found
Any Idea how to stop this?
if you read the api documentation for #RestController
You see that the annotation constructor takes in a value that is described as:
The value may indicate a suggestion for a logical component name, to
be turned into a Spring bean in case of an autodetected component.
So it is used to set a name for the Bean that vill be created.
It is not used to set a url-mapping like you have done.
#RestController("api/v1/users")
You need to annotate your class with #RequestMapping and also add mappings to the #PostMapping and #GetMapping.
#RestController
#RequestMapping("/api/v1") // Add request mapping
public class FooBar {
#PostMapping("/users") // Add mapping here
public User bar() {
...
}
#GetMapping("/users") // Add mapping here
public List<User> foo() {
...
}
}
I have this #Bean redirecting requests to my Spring Boot backend.
#Bean
WebMvcConfigurer configurer () {
return new WebMvcConfigurerAdapter() {
#Override
public void addResourceHandlers (ResourceHandlerRegistry registry) {
registry.addResourceHandler("/data/static/images/**")
.addResourceLocations("file:" + System.getProperty("user.dir") + "/static/img/");
}
};
}
It works perfectly for URLs such as:
http://localhost:4200/data/static/images/champion/tiles/Ahri_0.jpg
But not for URLs such as:
http://localhost:4200/data/static/images/champion/tiles/Tahm%20Kench_0.jpg
The image is correctly shown in my Angular2 front end if the champion name does not contain any of: space, ampersand or single quote characters.
I ran a trace level logging debug and made both types of requests -- one with and without a "bad" character. Currently, it seems as if the backend searches for the correct file. However, it turns out that it claims it can't find it. I quintuple checked the file in my insanity, I know it is there and that the path printed is correct.
Here is an example log message:
2018-11-18 05:07:14.496 TRACE 9897 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Testing handler map [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#4d0bdef0] in DispatcherServlet with name 'dispatcherServlet'
2018-11-18 05:07:14.497 DEBUG 9897 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Matching patterns for request [/data/static/images/champion/tiles/Tahm Kench_0.jpg] are [/data/static/images/**, /**]
2018-11-18 05:07:14.497 DEBUG 9897 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : URI Template variables for request [/data/static/images/champion/tiles/Tahm Kench_0.jpg] are {}
2018-11-18 05:07:14.497 DEBUG 9897 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapping [/data/static/images/champion/tiles/Tahm Kench_0.jpg] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[URL [file:/home/nuradin/Development/Java/riot-api-interface/static/img/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver#5b5b59]]] and 1 interceptor
2018-11-18 05:07:14.497 TRACE 9897 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Testing handler adapter [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#132f4851]
2018-11-18 05:07:14.497 TRACE 9897 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Testing handler adapter [org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter#5b8d72dc]
2018-11-18 05:07:14.498 DEBUG 9897 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/data/static/images/champion/tiles/Tahm%20Kench_0.jpg] is: -1
2018-11-18 05:07:14.498 DEBUG 9897 --- [on(7)-127.0.0.1] sun.rmi.transport.tcp : RMI TCP Connection(7)-127.0.0.1: (port 34127) op = 82
2018-11-18 05:07:14.498 TRACE 9897 --- [nio-8080-exec-1] o.s.w.s.resource.PathResourceResolver : Resolving resource for request path "champion/tiles/Tahm Kench_0.jpg"
2018-11-18 05:07:14.498 TRACE 9897 --- [nio-8080-exec-1] o.s.w.s.resource.PathResourceResolver : Checking location: URL [file:/home/nuradin/Development/Java/riot-api-interface/static/img/]
EDIT: I've implemented the class in the accepted answer, and it's definitely working because I printed the resource name (after encoding the characters I had trouble with.) However, the result is still a 404 error.
Log is below. The champion/Aatrox2Epng bit is due to a println statement in the method #slimane posted below.
2018-11-18 05:56:40.509 TRACE 12951 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Testing handler adapter [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#465ac973]
2018-11-18 05:56:40.509 TRACE 12951 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Testing handler adapter [org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter#37df7ae5]
2018-11-18 05:56:40.509 DEBUG 12951 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/data/static/images/champion/Aatrox.png] is: -1
2018-11-18 05:56:40.509 TRACE 12951 --- [nio-8080-exec-1] o.s.w.s.r.CachingResourceResolver : Resolving resource for request path "champion/Aatrox.png"
2018-11-18 05:56:40.510 TRACE 12951 --- [nio-8080-exec-1] o.e.r.c.EncodedPathResourceResolver : Resolving resource for request path "champion/Aatrox.png"
2018-11-18 05:56:40.510 TRACE 12951 --- [nio-8080-exec-1] o.e.r.c.EncodedPathResourceResolver : Checking location: URL [file:/home/nuradin/Development/Java/riot-api-interface/static/8.23.1/img]
champion/Aatrox2Epng
2018-11-18 05:56:40.511 TRACE 12951 --- [nio-8080-exec-1] o.e.r.c.EncodedPathResourceResolver : No match for location: URL [file:/home/nuradin/Development/Java/riot-api-interface/static/8.23.1/img]
2018-11-18 05:56:40.511 TRACE 12951 --- [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler : No matching resource found - returning 404
2018-11-18 05:56:40.511 DEBUG 12951 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
another EDIT -- sorry for the confusion, I changed the path because I thought paths with periods would work now.
#Bean
WebMvcConfigurer configurer () {
return new WebMvcConfigurerAdapter() {
#Override
public void addResourceHandlers (ResourceHandlerRegistry registry) {
registry.addResourceHandler("/data/static/images/**")
.addResourceLocations("file:" + System.getProperty("user.dir") + "/static/8.23.1/img")
.resourceChain(true)
.addResolver(encodedPathResourceResolver());
}
};
}
define your own PathResourceResolver as below:
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.resource.PathResourceResolver;
import org.springframework.web.servlet.resource.ResourceResolver;
import java.io.IOException;
public class CustomPathResourceResolver extends PathResourceResolver implements ResourceResolver {
#Override
protected Resource getResource(String resourcePath, Resource location) throws IOException {
//fixes problems with whitespaces in url
resourcePath = resourcePath.replace(" ","%20");
return super.getResource(resourcePath, location);
}
}
and then register it in your configuration:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/data/static/images/**")
.addResourceLocations("file:" + System.getProperty("user.dir") + "/static/img/")
.resourceChain(true)
.addResolver(new CustomPathResourceResolver())
;
}
This fixed the Problem for me. Somehow the path was encoded 2 times.
This removes all URI encoding not just whitespaces.
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/resources/**")
.addResourceLocations("file:/Q:/Technik/")
.resourceChain(true)
.addResolver(new CustomPathResourceResolver());
}
public class CustomPathResourceResolver extends PathResourceResolver implements ResourceResolver {
#Override
protected Resource getResource(String resourcePath, Resource location) throws IOException {
//fixes problems with special chars in url
log.debug(resourcePath);
resourcePath = UriUtils.decode(resourcePath, "UTF-8");
log.debug(resourcePath);
resourcePath = UriUtils.decode(resourcePath, "UTF-8");
log.debug(resourcePath);
return super.getResource(resourcePath, location);
}
}