flow
flow copied to clipboard
NPE from WebIconsRequestMatcher
Description of the bug
This happens if you reload / at a suitable point during startup of an application. Once the app has fully started, this no longer reproduces.
java.lang.NullPointerException: Cannot invoke "com.vaadin.flow.server.VaadinService.getContext()" because "service" is null
com.vaadin.flow.spring.security.WebIconsRequestMatcher.initMatchers(WebIconsRequestMatcher.java:78)
com.vaadin.flow.spring.security.WebIconsRequestMatcher.<init>(WebIconsRequestMatcher.java:66)
com.vaadin.flow.spring.security.RequestUtil.isCustomWebIcon(RequestUtil.java:143)
org.springframework.security.web.util.matcher.RequestMatcher.matcher(RequestMatcher.java:48)
org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.check(RequestMatcherDelegatingAuthorizationManager.java:79)
org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.check(RequestMatcherDelegatingAuthorizationManager.java:48)
org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:95)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:117)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
Expected behavior
No exception
Minimal reproducible example
A new starter with authentication
Versions
- Vaadin / Flow version: 24.4.alpha 2
- Java version:
- OS version:
- Browser version (if applicable):
- Application Server (if applicable):
- IDE (if applicable):
The problem here is that during a reload, there are requests incoming before VaadinService completes its intialization.
Dispatching requests to a servlet before HttpServlet.init() is invoked seems a bit weird to me :thinking:
Sounds like some other issue we had before? Icons, pwa, something ?
A simple "fix" is to initialize WebIconsRequestMatcher in RequestUtil.isCustomWebIcon() only if VaadinService is available.
The drawback is that until we get VaadinService, the requests for PWA icons will not be considered public, and the response will be HTTP 401.
If we need a service instance to determine that a request is for a PWA icon, what other options are there than returning 401 if the request comes in before the service instance is available?
I have no quick alternatives in mind right now.
Maybe generating the icons at frontend build time and storing the paths somewhere so that the registry could read the list without waiting for VaadinService could help. It could be that we already have a ticket for this
But since the issue impacts only dev-mode during hot reload, I think that for the moment we can just add the null check when instantiating WebIconsRequestMatcher.
This ticket/PR has been released with Vaadin 24.4.0.alpha21 and is also targeting the upcoming stable 24.4.0 version.
This ticket/PR has been released with Vaadin 24.3.10.