springspring-bootspring-mvc

How do i prevent a spring boot webapplication from accepting http requests while it is still starting up?


I have a spring boot webapplication with a angular frontend. When i send a request using the angular app while the webapplication is still starting up it may occur that the webapplication can accept that request and will try processing it. I believe the application is capable of receiving requests the moment that the WebSecurityConfigurerAdapter extending class has been initialized.

This causes problems when the rest of the classes have yet to fully initialize. For instance, when i try to log out a user that is still logged in while the webapplication is starting up, it may cause a SQLException because it can't find the database table user yet.

How do i prevent the application from accepting requests until the final class (the one annotated with @SpringBootApplication) has been initialized?


Solution

  • Based on the hint of @Fullslack.dev i've come up with the following solution.

    @WebFilter(urlPatterns = {"/*"})
    public class MyFilter implements Filter, ApplicationListener<ApplicationReadyEvent> {
    
        private boolean webApplicationReadyToAcceptRequests = false;
    
        @Override 
        public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
            webApplicationReadyToAcceptRequests = true;
        }
        
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
                throws IOException, ServletException {
                if(!webApplicationReadyToAcceptRequests) {
                    httpServletResponse.setHeader("Retry-After","35");
                    httpServletResponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "The server is currently starting up. Please try again in a moment.");
                    return;
                }
                else
                    filterChain.doFilter(servletRequest, servletResponse);
                }
        }
    
    }
    

    This is a filter class where every request must pass through first before it is presented to the @Controller and/or @Service annotated classes. If the variable webApplicationReadyToAcceptRequests is still false then the filter won't pass on the request downstream, instead it will send an error message response with httpstatus 503 (service unavailable).

    Make sure you annotate atleast one of your @Configuration config classes with this:

    @ComponentScan(basePackages={ "FolderWhereMyFilterIsLocated"})
    

    This will make sure that spring is aware of the existence of the filter.