Issue
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 be fully initialized. For instance, when i try to logout a user that is still logged in on the frontend side, while the webapplication is still startting 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.
Answered By - Maurice
Answer Checked By - Katrina (JavaFixing Volunteer)