javaspringspring-bootinternal-server-error

Spring boot 404 error handling default behavior


I have a spring boot application with no error handling for 404/500/403 etc just some templates placed in /resources/templates/error/*.html. You can assume that * is replaced with the specific error code such as 404.html. Now to my understanding Spring boot is smart enough to go and grab one of these with no further configuration needed which is great. However, if you look on the code below for 404 while the page is displayed for both the virtual server and the deployed server, on the latter it does not produce any of the thymeleaf variables i.e. they are empty.

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
  xmlns:th="http://www.thymeleaf.org"
  xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
  layout:decorate="~{layout}">
  <head>
     <title>Error</title>
  </head>
  <body>
   <div layout:fragment="content">
   <div class="container-fluid">
   <div class="header text-center">
    <h3 class="title" id="elementtitle" data-type="text" data-pk="1" data-url="/post">An 
    error occurred</h3>
   </div>
   <div class="row">
   <div class="col-md-6">
   <div class="card">
   <div class="card-header card-header-text card-header-primary">
    <div class="card-text">
      <h4 class="card-title">404 Not Found</h4>
    </div>
   </div>
   <div class="card-body">
     <p>The requested resource could not be found.<a th:href="'hidden for privacy 
    purposes' + ${path}"   title="Error contact">Hidden for privacy purposes</a></p>
      <div class="alert alert-info"> 
         Application: Application<br/>
         Path: [[${path}]]<br/>
         Message: [[${message}]]<br/>
         Previous URL: <data th:text="${#httpServletRequest.getHeader('Referer')}"/> 
          <br/>
         Username: <data sec:authentication="name"/><br/>
         Time: [[${timestamp}]]
      </div>
     </div>
  </div>
 </div>
</div>
</div>
</div>
</body>
</html>

As I already mentioned, all the thymeleaf variables are empty on the deployed server while on a virtual server (localhost) is fine. Could anyone with more experience in spring boot let me know why this behavior happens. My next steps are to implement logic to handle the server errors but I was just curious why this happens as it is not something you will find in a tutorial.

Thank you in advance.


Solution

  • Solved it. Apparently Spring boot on a deploy-able remote server clears the Authentication object from the SecurityContextHolder for security purposes when an error occurs, therefore if you need to propagate a page requiring user authentication after capturing /error, it will not be possible by default. What I have done to solve it is 1) make a persistent SecurityContextFilter and added an intercept for preHandle and postHandle of an HttpServletRequest to basically get the Authentication object, store it in another attribute in the request and while in the ErrorController you get it again and set the:

    SecurityContextHolder.getContext().setAuthentication(retrievedAuthentication);
    

    and it works like a charm.