How to show custom 404 page when user enters invalid url in spring boot application?

I am using java config in spring boot, spring security application. I configured the error controller as shown below. But whenever I enter an invalid URL, it goes into error.jsp , which is configured to handle application errors:

 @Controller public class AppErrorController implements ErrorController { private static final String PATH = "/error"; @RequestMapping(value = "/pageNotFound", method = { RequestMethod.GET, RequestMethod.POST }) public String pageNotFound() { return "pageNotFound"; } @RequestMapping(value = "/accessDenied", method = { RequestMethod.GET, RequestMethod.POST }) public String accessDenied() { return "accessDenied"; } @RequestMapping(value = PATH) public String error() { return "error"; } @Override public String getErrorPath() { return PATH; } } 

web.xml

 <error-page> <error-code>404</error-code> <location>/pageNotFound</location> </error-page> <error-page> <error-code>500</error-code> <location>/error</location> </error-page> 

404 is never called when an invalid URL is entered.

In addition, I do not use the built-in tomcat. I apply war to the outside of the cat. I have this in my application.yml file:

 server: error: whitelabel: enabled: false 

The following is the log if I enter the wrong URL. There are no errors. It simply redirects to /error in case of an invalid URL:

 2016-03-15 10:02:45.061 DEBUG 9997 --- [io-8080-exec-22] osbcweb.OrderedRequestContextFilter : Bound request context to thread: org.apache.catalina.connector.RequestFacade@371ef2a3 2016-03-15 10:02:45.061 DEBUG 9997 --- [io-8080-exec-22] osswumatcher.AntPathRequestMatcher : Checking match of request : '/donotexisturl'; against '/static/**' 2016-03-15 10:02:45.061 DEBUG 9997 --- [io-8080-exec-22] osswumatcher.AntPathRequestMatcher : Checking match of request : '/donotexisturl'; against '/i18n/**' 2016-03-15 10:02:45.061 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL at position 1 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' 2016-03-15 10:02:45.061 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 2016-03-15 10:02:45.061 DEBUG 9997 --- [io-8080-exec-22] wcHttpSessionSecurityContextRepository : Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: ' org.springframework.security.core.context.SecurityContextImpl@b8 db0c9d: Authentication: org.springframew ork.security.authentication.UsernamePasswordAuthenticationToken@ b8db0c9d: Principal: User{id=8, firstname='Adam', lastname='Milne', email=' adam.milne@abcd.com ', roleId=1}; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin gframework.security.web.authentication.WebAuthenticationDetails@ fffd148a: RemoteIpAddress: 127.0.0.1; SessionId: FED1F23633671F6E257CA9C5AFCEE216; Granted Authorities: ModuleOperation{moduleOperationId=1, moduleOperationName='roleList', moduleId=2, moduleName='role'}, ModuleOperation{moduleOperationId=8, moduleOperationName='deleteUser', moduleId=1, moduleName='user'}' 2016-03-15 10:02:45.061 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL at position 3 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter' 2016-03-15 10:02:45.061 DEBUG 9997 --- [io-8080-exec-22] osswheader.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.se curity.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@ 6e929f31 2016-03-15 10:02:45.061 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL at position 4 of 13 in additional filter chain; firing Filter: 'CsrfFilter' 2016-03-15 10:02:45.061 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL at position 5 of 13 in additional filter chain; firing Filter: 'LogoutFilter' 2016-03-15 10:02:45.061 DEBUG 9997 --- [io-8080-exec-22] osswumatcher.AntPathRequestMatcher : Request 'GET /donotexisturl' doesn't match 'POST /logout 2016-03-15 10:02:45.061 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL at position 6 of 13 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' 2016-03-15 10:02:45.061 DEBUG 9997 --- [io-8080-exec-22] osswumatcher.AntPathRequestMatcher : Request 'GET /donotexisturl' doesn't match 'POST /checklogin 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL at position 7 of 13 in additional filter chain; firing Filter: 'ConcurrentSessionFilter' 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL at position 8 of 13 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL at position 9 of 13 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL at position 10 of 13 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] osswaAnonymousAuthenticationFilter : SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframew ork.security.authentication.UsernamePasswordAuthenticationToken@ b8db0c9d: Principal: User{id=8, firstname='Adam', lastname='Milne', email=' adam.milne@abcd.com ', roleId=1}; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin gframework.security.web.authentication.WebAuthenticationDetails@ fffd148a: RemoteIpAddress: 127.0.0.1; SessionId: FED1F23633671F6E257CA9C5AFCEE216; Granted Authorities: ModuleOperation{moduleOperationId=1, moduleOperationName='roleList', moduleId=2, moduleName='role'}, ModuleOperation{moduleOperationId=8, moduleOperationName='deleteUser', moduleId=1, moduleName='user'}' 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL at position 11 of 13 in additional filter chain; firing Filter: 'SessionManagementFilter' 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL at position 12 of 13 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL at position 13 of 13 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] osswumatcher.AntPathRequestMatcher : Request 'GET /donotexisturl' doesn't match 'POST /logout 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] osswumatcher.AntPathRequestMatcher : Checking match of request : '/donotexisturl'; against '/login**' 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] osswumatcher.AntPathRequestMatcher : Checking match of request : '/donotexisturl'; against '/error**' 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] osswumatcher.AntPathRequestMatcher : Checking match of request : '/donotexisturl'; against '/checklogin**' 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] osswaiFilterSecurityInterceptor : Secure object: FilterInvocation: URL: /doNotExistURL; Attributes: [fullyAuthenticated] 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] osswaiFilterSecurityInterceptor : Previously Authenticated: org.springframew ork.security.authentication.UsernamePasswordAuthenticationToken@ b8db0c9d: Principal: User{id=8, firstname='Adam', lastname='Milne', email=' adam.milne@abcd.com ', roleId=1}; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin gframework.security.web.authentication.WebAuthenticationDetails@ fffd148a: RemoteIpAddress: 127.0.0.1; SessionId: FED1F23633671F6E257CA9C5AFCEE216; Granted Authorities: ModuleOperation{moduleOperationId=1, moduleOperationName='roleList', moduleId=2, moduleName='role'}, ModuleOperation{moduleOperationId=8, moduleOperationName='deleteUser', moduleId=1, moduleName='user'} 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] ossecurity.access.vote.UnanimousBased : Voter: org.sp ringframework.security.web.access.expression.WebExpressionVoter@ 6ad88564, returned: 1 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] ossecurity.access.vote.UnanimousBased : Voter: org.springframework.security.access.vote.AuthenticatedVoter@1900 7bb6, returned: 0 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] ossecurity.access.vote.UnanimousBased : Voter: com.sts.app.core.user.security.AccessDecisionVoterImpl@1465b821 , returned: 1 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] osswaiFilterSecurityInterceptor : Authorization successful 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] osswaiFilterSecurityInterceptor : RunAsManager did not change Authentication object 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /doNotExistURL reached end of additional filter chain; proceeding with original chain 2016-03-15 10:02:45.062 DEBUG 9997 --- [io-8080-exec-22] osweb.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/gen/doNotExistURL] 2016-03-15 10:02:45.063 DEBUG 9997 --- [io-8080-exec-22] swsmmaRequestMappingHandlerMapping : Looking up handler method for path /doNotExistURL 2016-03-15 10:02:45.064 DEBUG 9997 --- [io-8080-exec-22] swsmmaRequestMappingHandlerMapping : Did not find handler method for [/doNotExistURL] 2016-03-15 10:02:45.064 DEBUG 9997 --- [io-8080-exec-22] oswshandler.SimpleUrlHandlerMapping : Matching patterns for request [/doNotExistURL] are [/**] 2016-03-15 10:02:45.064 DEBUG 9997 --- [io-8080-exec-22] oswshandler.SimpleUrlHandlerMapping : URI Template variables for request [/doNotExistURL] are {} 2016-03-15 10:02:45.064 DEBUG 9997 --- [io-8080-exec-22] oswshandler.SimpleUrlHandlerMapping : Mapping [/doNotExistURL] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[ServletContext resource [/], class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/]], resolvers=[ org.springframework.web.servlet.resource.PathResourceResolver@87 dd2cb]]] and 1 interceptor 2016-03-15 10:02:45.064 DEBUG 9997 --- [io-8080-exec-22] osweb.servlet.DispatcherServlet : Last-Modified value for [/gen/doNotExistURL] is: -1 2016-03-15 10:02:45.077 DEBUG 9997 --- [io-8080-exec-22] osweb.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] osweb.servlet.DispatcherServlet : Successfully completed request 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] osswaExceptionTranslationFilter : Chain processed normally 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] sswcSecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] osbcweb.OrderedRequestContextFilter : Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@371ef2a3 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] osbcweb.OrderedRequestContextFilter : Bound request context to thread: org.apache.catalina.core.ApplicationHttpRequest@20ae74b1 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] osswumatcher.AntPathRequestMatcher : Checking match of request : '/error'; against '/static/**' 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] osswumatcher.AntPathRequestMatcher : Checking match of request : '/error'; against '/i18n/**' 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error at position 1 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] wcHttpSessionSecurityContextRepository : Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: ' org.springframework.security.core.context.SecurityContextImpl@b8 db0c9d: Authentication: org.springframew ork.security.authentication.UsernamePasswordAuthenticationToken@ b8db0c9d: Principal: User{id=8, firstname='Adam', lastname='Milne', email=' adam.milne@abcd.com ', roleId=1}; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin gframework.security.web.authentication.WebAuthenticationDetails@ fffd148a: RemoteIpAddress: 127.0.0.1; SessionId: FED1F23633671F6E257CA9C5AFCEE216; Granted Authorities: ModuleOperation{moduleOperationId=1, moduleOperationName='roleList', moduleId=2, moduleName='role'}, ModuleOperation{moduleOperationId=8, moduleOperationName='deleteUser', moduleId=1, moduleName='user'}' 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error at position 3 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter' 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error at position 4 of 13 in additional filter chain; firing Filter: 'CsrfFilter' 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error at position 5 of 13 in additional filter chain; firing Filter: 'LogoutFilter' 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] osswumatcher.AntPathRequestMatcher : Request 'GET /error' doesn't match 'POST /logout 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error at position 6 of 13 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' 2016-03-15 10:02:45.078 DEBUG 9997 --- [io-8080-exec-22] osswumatcher.AntPathRequestMatcher : Request 'GET /error' doesn't match 'POST /checklogin 2016-03-15 10:02:45.079 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error at position 7 of 13 in additional filter chain; firing Filter: 'ConcurrentSessionFilter' 2016-03-15 10:02:45.079 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error at position 8 of 13 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' 2016-03-15 10:02:45.079 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error at position 9 of 13 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' 2016-03-15 10:02:45.079 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error at position 10 of 13 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' 2016-03-15 10:02:45.079 DEBUG 9997 --- [io-8080-exec-22] osswaAnonymousAuthenticationFilter : SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframew ork.security.authentication.UsernamePasswordAuthenticationToken@ b8db0c9d: Principal: User{id=8, firstname='Adam', lastname='Milne', email=' adam.milne@abcd.com ', roleId=1}; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin gframework.security.web.authentication.WebAuthenticationDetails@ fffd148a: RemoteIpAddress: 127.0.0.1; SessionId: FED1F23633671F6E257CA9C5AFCEE216; Granted Authorities: ModuleOperation{moduleOperationId=1, moduleOperationName='roleList', moduleId=2, moduleName='role'}, ModuleOperation{moduleOperationId=8, moduleOperationName='deleteUser', moduleId=1, moduleName='user'}' 2016-03-15 10:02:45.079 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error at position 11 of 13 in additional filter chain; firing Filter: 'SessionManagementFilter' 2016-03-15 10:02:45.079 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error at position 12 of 13 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' 2016-03-15 10:02:45.079 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error at position 13 of 13 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' 2016-03-15 10:02:45.079 DEBUG 9997 --- [io-8080-exec-22] ossecurity.web.FilterChainProxy : /error reached end of additional filter chain; proceeding with original chain 2016-03-15 10:02:45.079 DEBUG 9997 --- [io-8080-exec-22] osweb.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/gen/error] 2016-03-15 10:02:45.079 DEBUG 9997 --- [io-8080-exec-22] swsmmaRequestMappingHandlerMapping : Looking up handler method for path /error 2016-03-15 10:02:45.079 DEBUG 9997 --- [io-8080-exec-22] swsmmaRequestMappingHandlerMapping : Returning handler method [public java.lang.String com.sts.app.core.common.web.AppErrorController.error()] 
+3
source share
4 answers

First of all, define an exception for each specific HTTP error that you are going to handle. Here, I simply define one to handle 404 Not Found case:

 public class NotFoundException extends RuntimeException {} 

In order to completely replace the default error handling mechanism of Spring Boot, we can implement ErrorController . Instead of just embedding ErrorController , here I extend AbstractErrorController , which implements ErrorController and provides some helper methods like getStatus() .

In any case, the main idea is to handle all errors using the endpoint, say /error , and throw these predefined exceptions in the case of their respective HTTP status codes:

 @Controller public class CustomErrorController extends AbstractErrorController { private static final String ERROR_PATH= "/error"; @Autowired public CustomErrorController(ErrorAttributes errorAttributes) { super(errorAttributes); } /** * Just catching the {@linkplain NotFoundException} exceptions and render * the 404.jsp error page. */ @ExceptionHandler(NotFoundException.class) public String notFound() { return "404"; } /** * Responsible for handling all errors and throw especial exceptions * for some HTTP status codes. Otherwise, it will return a map that * ultimately will be converted to a json error. */ @RequestMapping(ERROR_PATH) public ResponseEntity<?> handleErrors(HttpServletRequest request) { HttpStatus status = getStatus(request); if (status.equals(HttpStatus.NOT_FOUND)) throw new NotFoundException(); return ResponseEntity.status(status).body(getErrorAttributes(request, false)); } @Override public String getErrorPath() { return ERROR_PATH; } } 

Of course, this solution is only suitable for traditional deployment. If you plan to use the built-in servlet container, you better define the EmbeddedServletContainerCustomizer .

+1
source

If you want to add this @Bean to the spring application configuration, for example:

 @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return new EmbeddedServletContainerCustomizer() { @Override public void customize(ConfigurableEmbeddedServletContainer container) { ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/error404.html"); container.addErrorPages(error404Page); } }; } 

and put error404.html in your static folder.

Link: http://www.sporcic.org/2014/05/custom-error-pages-with-spring-boot/

+2
source

Here you go

 @RestController public class RestErrorController implements ErrorController{ private static final String PATH = "/error"; @Autowired private ErrorAttributes errorAttributes; @RequestMapping(value=PATH,method=RequestMethod.GET) public ApiErrorExtended error(HttpServletRequest request, HttpServletResponse response){ return new ApiErrorExtended( response.getStatus(),getErrorAttributes(request, true)); } private Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) { RequestAttributes requestAttributes = new ServletRequestAttributes(request); return errorAttributes.getErrorAttributes(requestAttributes, includeStackTrace); } public String getErrorPath() { return PATH; } } 

This is my resting error controller. You can change it to return whatever you want.

0
source

hi, you only need to configure the following:

 <error-page> <error-code>404</error-code> <location>/pageNotFound/404.jsp</location> </error-page> 

and you are setting up a Java exception:

 <error-page> <exception-type>java.lang.Exception</exception-type> <location>/pageNotFound/exception.jsp</location> 

0
source

Source: https://habr.com/ru/post/1244710/


All Articles