Skip to content

"setAttribute is not supported" error from PathPatternRequestMatcher in child context with Spring Security 6.5.7 #19219

@ThrawnCA

Description

@ThrawnCA

Describe the bug

We are attempting to update an application from Java EE8 to EE9, including moving from Spring Security 5 to 6.5.7, and replacing AntPathRequestMatcher with PathPatternRequestMatcher. However, this results in java.lang.UnsupportedOperationException: public abstract void jakarta.servlet.ServletRequest.setAttribute(java.lang.String,java.lang.Object) is not supported when the matcher is used.

jakarta.servlet.ServletException: Request processing failed: java.lang.UnsupportedOperationException: public abstract void jakarta.servlet.ServletRequest.setAttribute(java.lang.String,java.lang.Object) is not supported
    at org.springframework.web.servlet.FrameworkServlet.processRequest (FrameworkServlet.java:1022)
    at org.springframework.web.servlet.FrameworkServlet.doGet (FrameworkServlet.java:903)
    at jakarta.servlet.http.HttpServlet.service (HttpServlet.java:527)
    at org.springframework.web.servlet.FrameworkServlet.service (FrameworkServlet.java:885)
    at jakarta.servlet.http.HttpServlet.service (HttpServlet.java:614)
    at org.eclipse.jetty.ee10.servlet.ServletHolder$NotAsync.service (ServletHolder.java:1397)
    at org.eclipse.jetty.ee10.servlet.ServletHolder.handle (ServletHolder.java:754)
    at org.eclipse.jetty.ee10.servlet.ServletHandler$ChainEnd.doFilter (ServletHandler.java:1622)
    at org.eclipse.jetty.ee10.servlet.ServletHandler$MappedServlet.handle (ServletHandler.java:1556)
    at org.eclipse.jetty.ee10.servlet.Dispatcher.forward (Dispatcher.java:135)
    at org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequestDispatcher.forward (HeaderWriterFilter.java:170)
    at org.springframework.security.web.access.AccessDeniedHandlerImpl.handle (AccessDeniedHandlerImpl.java:72)
    at org.springframework.security.web.access.ExceptionTranslationFilter.handleAccessDeniedException (ExceptionTranslationFilter.java:208)
    at org.springframework.security.web.access.ExceptionTranslationFilter.handleSpringSecurityException (ExceptionTranslationFilter.java:177)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter (ExceptionTranslationFilter.java:146)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter (ExceptionTranslationFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at au.com.citec.rads.web.auth.ForceChangePasswordFilter.doFilter (ForceChangePasswordFilter.java:53)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter (AnonymousAuthenticationFilter.java:100)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter (SecurityContextHolderAwareRequestFilter.java:179)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter (RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter (AbstractAuthenticationProcessingFilter.java:235)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter (AbstractAuthenticationProcessingFilter.java:229)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter (LogoutFilter.java:107)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter (LogoutFilter.java:93)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal (CsrfFilter.java:117)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter (HeaderWriterFilter.java:90)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal (HeaderWriterFilter.java:75)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter (SecurityContextHolderFilter.java:82)
    at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter (SecurityContextHolderFilter.java:69)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal (WebAsyncManagerIntegrationFilter.java:62)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal (DisableEncodeUrlFilter.java:42)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal (FilterChainProxy.java:233)
    at org.springframework.security.web.FilterChainProxy.doFilter (FilterChainProxy.java:191)
    at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter (CompositeFilter.java:113)
    at org.springframework.web.filter.ServletRequestPathFilter.doFilter (ServletRequestPathFilter.java:52)
    at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter (CompositeFilter.java:113)
    at org.springframework.web.filter.CompositeFilter.doFilter (CompositeFilter.java:74)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$CompositeFilterChainProxy.doFilter (WebSecurityConfiguration.java:319)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate (DelegatingFilterProxy.java:362)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter (DelegatingFilterProxy.java:278)
    at org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter (FilterHolder.java:205)
    at org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter (ServletHandler.java:1594)
    at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal (MultipartFilter.java:125)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:116)
    at org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter (FilterHolder.java:208)
    at org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter (ServletHandler.java:1594)
    at org.eclipse.jetty.ee10.servlet.ServletHandler$MappedServlet.handle (ServletHandler.java:1556)
    at org.eclipse.jetty.ee10.servlet.ServletChannel.dispatch (ServletChannel.java:871)
    at org.eclipse.jetty.ee10.servlet.ServletChannel.handle (ServletChannel.java:449)
    at org.eclipse.jetty.ee10.servlet.ServletHandler.handle (ServletHandler.java:469)
    at org.eclipse.jetty.security.SecurityHandler.handle (SecurityHandler.java:546)
    at org.eclipse.jetty.ee10.servlet.SessionHandler.handle (SessionHandler.java:719)
    at org.eclipse.jetty.server.handler.ContextHandler.handle (ContextHandler.java:1250)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle (ContextHandlerCollection.java:148)
    at org.eclipse.jetty.server.Server.handle (Server.java:197)
    at org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run (HttpChannelState.java:793)
    at org.eclipse.jetty.server.internal.HttpConnection.onFillable (HttpConnection.java:419)
    at org.eclipse.jetty.server.internal.HttpConnection$FillableCallback.succeeded (HttpConnection.java:1780)
    at org.eclipse.jetty.io.FillInterest.fillable (FillInterest.java:105)
    at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run (SelectableChannelEndPoint.java:54)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask (AdaptiveExecutionStrategy.java:492)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.epcRunTask (AdaptiveExecutionStrategy.java:428)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask (AdaptiveExecutionStrategy.java:401)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce (AdaptiveExecutionStrategy.java:255)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run (AdaptiveExecutionStrategy.java:204)
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run (ReservedThreadExecutor.java:317)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob (QueuedThreadPool.java:1009)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob (QueuedThreadPool.java:1240)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run (QueuedThreadPool.java:1194)
    at java.lang.Thread.run (Thread.java:840)
Caused by: java.lang.UnsupportedOperationException: public abstract void jakarta.servlet.ServletRequest.setAttribute(java.lang.String,java.lang.Object) is not supported
    at org.springframework.security.web.FilterInvocation$UnsupportedOperationExceptionInvocationHandler.invoke (FilterInvocation.java:331)
    at jdk.proxy5.$Proxy218.setAttribute (Unknown Source)
    at jakarta.servlet.ServletRequestWrapper.setAttribute (ServletRequestWrapper.java:238)
    at org.springframework.web.util.ServletRequestPathUtils.parseAndCache (ServletRequestPathUtils.java:71)
    at org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.getPathContainer (PathPatternRequestMatcher.java:119)
    at org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.matcher (PathPatternRequestMatcher.java:108)
    at org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.matches (PathPatternRequestMatcher.java:97)
    at org.springframework.security.web.util.matcher.OrRequestMatcher.matches (OrRequestMatcher.java:59)
    at org.springframework.security.web.DefaultSecurityFilterChain.matches (DefaultSecurityFilterChain.java:89)
    at org.springframework.security.web.util.matcher.RequestMatcher.matcher (RequestMatcher.java:48)
    at org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.check (RequestMatcherDelegatingAuthorizationManager.java:83)
    at org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.check (RequestMatcherDelegatingAuthorizationManager.java:50)
    at org.springframework.security.authorization.AuthorizationManager.authorize (AuthorizationManager.java:69)
    at org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator.isAllowed (AuthorizationManagerWebInvocationPrivilegeEvaluator.java:60)
    at org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator.isAllowed (RequestMatcherDelegatingWebInvocationPrivilegeEvaluator.java:114)
    at org.springframework.security.taglibs.authz.AbstractAuthorizeTag.authorizeUsingUrlCheck (AbstractAuthorizeTag.java:149)
    at org.springframework.security.taglibs.authz.AbstractAuthorizeTag.authorize (AbstractAuthorizeTag.java:103)
    at org.springframework.security.taglibs.authz.JspAuthorizeTag.doStartTag (JspAuthorizeTag.java:70)
    at freemarker.ext.jakarta.jsp.TagTransformModel$TagWriter.onStart (TagTransformModel.java:322)
    at freemarker.core.Environment.visitAndTransform (Environment.java:509)
    at freemarker.core.UnifiedCall.accept (UnifiedCall.java:103)
    at freemarker.core.Environment.visit (Environment.java:380)
    at freemarker.core.Environment.visitAndTransform (Environment.java:511)
    at freemarker.core.UnifiedCall.accept (UnifiedCall.java:103)
    at freemarker.core.Environment.visit (Environment.java:380)
    at freemarker.core.Environment.visitAndTransform (Environment.java:511)
    at freemarker.core.UnifiedCall.accept (UnifiedCall.java:103)
    at freemarker.core.Environment.visit (Environment.java:380)
    at freemarker.core.Environment.invokeMacroOrFunctionCommonPart (Environment.java:886)
    at freemarker.core.Environment.invokeMacro (Environment.java:822)
    at freemarker.core.UnifiedCall.accept (UnifiedCall.java:83)
    at freemarker.core.Environment.visit (Environment.java:380)
    at freemarker.core.Environment.invokeNestedContent (Environment.java:630)
    at freemarker.core.BodyInstruction.accept (BodyInstruction.java:60)
    at freemarker.core.Environment.visit (Environment.java:380)
    at freemarker.core.Environment.invokeMacroOrFunctionCommonPart (Environment.java:886)
    at freemarker.core.Environment.invokeMacro (Environment.java:822)
    at freemarker.core.UnifiedCall.accept (UnifiedCall.java:83)
    at freemarker.core.Environment.visit (Environment.java:344)
    at freemarker.core.Environment.visit (Environment.java:350)
    at freemarker.core.Environment.process (Environment.java:323)
    at org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate (FreeMarkerView.java:447)
    at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender (FreeMarkerView.java:351)
    at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel (FreeMarkerView.java:302)
    at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel (AbstractTemplateView.java:181)
    at org.springframework.web.servlet.view.AbstractView.render (AbstractView.java:314)
    at org.springframework.web.servlet.DispatcherServlet.render (DispatcherServlet.java:1438)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult (DispatcherServlet.java:1168)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch (DispatcherServlet.java:1106)
    at org.springframework.web.servlet.DispatcherServlet.doService (DispatcherServlet.java:979)
    at org.springframework.web.servlet.FrameworkServlet.processRequest (FrameworkServlet.java:1014)
    at org.springframework.web.servlet.FrameworkServlet.doGet (FrameworkServlet.java:903)
    at jakarta.servlet.http.HttpServlet.service (HttpServlet.java:527)
    at org.springframework.web.servlet.FrameworkServlet.service (FrameworkServlet.java:885)
    at jakarta.servlet.http.HttpServlet.service (HttpServlet.java:614)
    at org.eclipse.jetty.ee10.servlet.ServletHolder$NotAsync.service (ServletHolder.java:1397)
    at org.eclipse.jetty.ee10.servlet.ServletHolder.handle (ServletHolder.java:754)
    at org.eclipse.jetty.ee10.servlet.ServletHandler$ChainEnd.doFilter (ServletHandler.java:1622)
    at org.eclipse.jetty.ee10.servlet.ServletHandler$MappedServlet.handle (ServletHandler.java:1556)
    at org.eclipse.jetty.ee10.servlet.Dispatcher.forward (Dispatcher.java:135)
    at org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequestDispatcher.forward (HeaderWriterFilter.java:170)
    at org.springframework.security.web.access.AccessDeniedHandlerImpl.handle (AccessDeniedHandlerImpl.java:72)
    at org.springframework.security.web.access.ExceptionTranslationFilter.handleAccessDeniedException (ExceptionTranslationFilter.java:208)
    at org.springframework.security.web.access.ExceptionTranslationFilter.handleSpringSecurityException (ExceptionTranslationFilter.java:177)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter (ExceptionTranslationFilter.java:146)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter (ExceptionTranslationFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at au.com.citec.rads.web.auth.ForceChangePasswordFilter.doFilter (ForceChangePasswordFilter.java:53)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter (AnonymousAuthenticationFilter.java:100)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter (SecurityContextHolderAwareRequestFilter.java:179)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter (RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter (AbstractAuthenticationProcessingFilter.java:235)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter (AbstractAuthenticationProcessingFilter.java:229)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter (LogoutFilter.java:107)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter (LogoutFilter.java:93)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal (CsrfFilter.java:117)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter (HeaderWriterFilter.java:90)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal (HeaderWriterFilter.java:75)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter (SecurityContextHolderFilter.java:82)
    at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter (SecurityContextHolderFilter.java:69)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal (WebAsyncManagerIntegrationFilter.java:62)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal (DisableEncodeUrlFilter.java:42)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:374)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal (FilterChainProxy.java:233)
    at org.springframework.security.web.FilterChainProxy.doFilter (FilterChainProxy.java:191)
    at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter (CompositeFilter.java:113)
    at org.springframework.web.filter.ServletRequestPathFilter.doFilter (ServletRequestPathFilter.java:52)
    at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter (CompositeFilter.java:113)
    at org.springframework.web.filter.CompositeFilter.doFilter (CompositeFilter.java:74)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$CompositeFilterChainProxy.doFilter (WebSecurityConfiguration.java:319)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate (DelegatingFilterProxy.java:362)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter (DelegatingFilterProxy.java:278)
    at org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter (FilterHolder.java:205)
    at org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter (ServletHandler.java:1594)
    at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal (MultipartFilter.java:125)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:116)
    at org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter (FilterHolder.java:208)
    at org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter (ServletHandler.java:1594)
    at org.eclipse.jetty.ee10.servlet.ServletHandler$MappedServlet.handle (ServletHandler.java:1556)
    at org.eclipse.jetty.ee10.servlet.ServletChannel.dispatch (ServletChannel.java:871)
    at org.eclipse.jetty.ee10.servlet.ServletChannel.handle (ServletChannel.java:449)
    at org.eclipse.jetty.ee10.servlet.ServletHandler.handle (ServletHandler.java:469)
    at org.eclipse.jetty.security.SecurityHandler.handle (SecurityHandler.java:546)
    at org.eclipse.jetty.ee10.servlet.SessionHandler.handle (SessionHandler.java:719)
    at org.eclipse.jetty.server.handler.ContextHandler.handle (ContextHandler.java:1250)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle (ContextHandlerCollection.java:148)
    at org.eclipse.jetty.server.Server.handle (Server.java:197)
    at org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run (HttpChannelState.java:793)
    at org.eclipse.jetty.server.internal.HttpConnection.onFillable (HttpConnection.java:419)
    at org.eclipse.jetty.server.internal.HttpConnection$FillableCallback.succeeded (HttpConnection.java:1780)
    at org.eclipse.jetty.io.FillInterest.fillable (FillInterest.java:105)
    at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run (SelectableChannelEndPoint.java:54)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask (AdaptiveExecutionStrategy.java:492)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.epcRunTask (AdaptiveExecutionStrategy.java:428)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask (AdaptiveExecutionStrategy.java:401)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce (AdaptiveExecutionStrategy.java:255)
    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run (AdaptiveExecutionStrategy.java:204)
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run (ReservedThreadExecutor.java:317)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob (QueuedThreadPool.java:1009)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob (QueuedThreadPool.java:1240)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run (QueuedThreadPool

To Reproduce

Visit any page post-login.

Expected behavior

Pages should load normally

Sample

Our web application initializer is configured with:

@Override
public void onStartup(final ServletContext sc) {
    sc.setInitParameter("defaultHtmlEscape", "true");

    sc.addFilter("charsetFilter", new CharacterEncodingFilter("UTF-8", true))
        .addMappingForUrlPatterns(null, true, "/*");

    /*
     * Multipart resolution needs to come before Spring Security
     * so that CSRF tokens are visible.
     */
    sc.addFilter("springMultipartResolver", org.springframework.web.multipart.support.MultipartFilter.class)
        .addMappingForUrlPatterns(null, false, "/*");

    sc.addFilter("springSecurityFilterChain", org.springframework.web.filter.DelegatingFilterProxy.class)
        .addMappingForUrlPatterns(null, false, "/*");

    sc.addFilter("welcomePageFilter", au.com.citec.rads.web.filter.RedirectFilter.class)
        .addMappingForUrlPatterns(null, true, "/");

    sc.addFilter("clickjackFilter", org.owasp.esapi.filters.ClickjackFilter.class)
        .addMappingForUrlPatterns(null, true, "/*");

    AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
    root.register(SpringCoreConfig.class, SpringSecurityConfig.class);

    AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
    root.register(SpringCoreConfig.class, SpringSecurityConfig.class);

    AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
    dispatcherContext.register(SpringServletConfig.class);
    ServletRegistration.Dynamic servlet = sc.addServlet("rads", new DispatcherServlet(dispatcherContext));
    servlet.setLoadOnStartup(1);
    servlet.setMultipartConfig(
        new MultipartConfigElement("", 10485760L, 10485760L, 0)  // 10MB (10485760 bytes)
    );
    servlet.addMapping("/web/*");

    dispatcherContext = new AnnotationConfigWebApplicationContext();
    dispatcherContext.register(SpringRestConfig.class);
    servlet = sc.addServlet("restful", new DispatcherServlet(dispatcherContext));
    servlet.setLoadOnStartup(2);
    servlet.addMapping("/rest/*");

    dispatcherContext = new AnnotationConfigWebApplicationContext();
    dispatcherContext.register(SpringWebServiceConfig.class);
    servlet = sc.addServlet("rads-ws", new MessageDispatcherServlet(dispatcherContext));
    servlet.setLoadOnStartup(3);
    servlet.addMapping("/ws/*");

    sc.addListener(new ContextLoaderListener(root));
}

SpringCoreConfig.java merely defines general application beans like the data layer.

SpringSecurityConfig.java includes the relevant request matcher that triggers the exception:

@Bean
@Order(2)
public SecurityFilterChain servletFilterChain(HttpSecurity http) throws Exception {
    PathPatternRequestMatcher appPath = PathPatternRequestMatcher.withDefaults().basePath("/web");
    return http.addFilterAfter(forceChangePasswordFilter, AnonymousAuthenticationFilter.class)
        .formLogin(loginConfig -> loginConfig
            ...
        )
        .logout(logoutConfig -> logoutConfig
            ...
        )
        .exceptionHandling(exception -> exception.accessDeniedPage("/web/security/accessDenied"))
        .authorizeHttpRequests(authz -> authz
            .requestMatchers(appPath.matcher(("/security/login")).anonymous()
            ...
        )
        .build();

SpringServletConfig.java contains:

package au.com.citec.rads.config;

import java.lang.invoke.MethodHandles;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.util.Map;
import java.util.Properties;

import au.com.citec.rads.ReferenceService;
import au.com.citec.rads.common.BillingFee;
import au.com.citec.rads.common.Money;
import au.com.citec.rads.domain.FinancialAdjustment;
import au.com.citec.rads.domain.MerchantFee;
import au.com.citec.rads.domain.Payment;
import au.com.citec.rads.domain.enumtype.RateType;
import au.com.citec.rads.domain.reference.Agency;
import au.com.citec.rads.domain.reference.BillingRuleApplication;
import au.com.citec.rads.domain.reference.BusinessArea;
import au.com.citec.rads.domain.reference.Channel;
import au.com.citec.rads.domain.reference.Service;
import au.com.citec.rads.domain.reference.SubChannel;
import au.com.citec.rads.web.controller.FileBrowserController;
import au.com.citec.rads.web.convert.*;
import au.com.citec.rads.web.customview.FreeMarkerCSVView;
import au.com.citec.rads.web.customview.FreeMarkerDownloadView;
import au.com.citec.rads.web.customview.FreeMarkerPDFView;
import au.com.citec.rads.web.customview.FreeMarkerTXTView;
import au.com.citec.rads.web.interceptor.HelpPageInterceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.standard.Jsr310DateTimeFormatAnnotationFormatterFactory;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
import org.springframework.web.servlet.ViewResolver;

@Configuration
@ComponentScan(
    basePackages = {"au.com.citec.rads.web", "au.com.citec.rads.rest"},
    excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = org.springframework.ws.server.endpoint.annotation.Endpoint.class),
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = FileBrowserController.class)
    }
)
@EnableWebMvc
@PropertySource({"classpath:environment.properties", "classpath:applicationConfig.properties"})
public class SpringServletConfig implements WebMvcConfigurer {

    private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

    @Value("file:${file.root.folder:failed}/interfaces")
    private Resource interfacesRoot;

    @Value("file:${archive.root.folder:failed}")
    private Resource archiveRoot;

    @Value("file:${file.root.folder:failed}/reports")
    private Resource reportsRoot;

    @Autowired
    private ReferenceService referenceService;

    @Autowired
    private HelpPageInterceptor helpPageInterceptor;

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatterForFieldType(BillingRuleApplication.class, new BillingRuleApplicationTypeFormatter());
        registry.addFormatterForFieldAnnotation(new RadsDateTimeFormatAnnotationFormatterFactory(new Jsr310DateTimeFormatAnnotationFormatterFactory()));
        registry.addFormatterForFieldType(Money.class, new MoneyFormatter());
        registry.addFormatterForFieldType(BillingFee.class, new BillingFeeFormatter());
        registry.addFormatterForFieldType(Payment.Discriminator.class, new PaymentDiscriminatorFormatter());
        registry.addFormatterForFieldType(MerchantFee.MerchantFeeType.class, new MerchantFeeTypeFormatter());
        registry.addFormatterForFieldType(RateType.class, new RateTypeFormatter());
        registry.addFormatterForFieldType(FinancialAdjustment.AdjustmentType.class, new FinancialAdjustmentTypeFormatter());
        registry.addFormatterForFieldType(Channel.class, new ChannelFormatter(referenceService));
        registry.addFormatterForFieldType(SubChannel.class, new SubChannelFormatter(referenceService));
        registry.addFormatterForFieldType(Agency.class, new AgencyFormatter(referenceService));
        registry.addFormatterForFieldType(Service.class, new ServiceFormatter(referenceService));
        registry.addFormatterForFieldType(BusinessArea.class, new BusinessAreaFormatter(referenceService));
        registry.addFormatterForFieldType(ZonedDateTime.class, new ZonedDateTimeFormatter());
        registry.addFormatterForFieldType(LocalDate.class, new LocalDateFormatter());
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(helpPageInterceptor);
    }

    @Bean
    public FreeMarkerConfigurer freemarkerConfig() {
        FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
        configurer.setTemplateLoaderPaths("/WEB-INF/templates/", "classpath:/templates");
        Properties freemarkerSettings = new Properties(5);
        freemarkerSettings.setProperty("object_wrapper", "au.com.citec.rads.JDKTimeAwareObjectWrapper");
        freemarkerSettings.setProperty("locale", "en_GB");
        freemarkerSettings.setProperty("number_format", "0");
        freemarkerSettings.setProperty("date_format", "dd/MM/yyyy");
        freemarkerSettings.setProperty("datetime_format", "dd/MM/yyyy HH:mm:ss");
        configurer.setFreemarkerSettings(freemarkerSettings);
        return configurer;
    }

    @Bean
    public ViewResolver radsStandardViewResolver() {
        FreeMarkerViewResolver resolver = new FreeMarkerViewResolver("", ".ftl");
        resolver.setCache(true);
        resolver.setContentType(MediaType.TEXT_HTML_VALUE);
        resolver.setExposeSpringMacroHelpers(true);
        return resolver;
    }

    private FreeMarkerViewResolver makeViewResolver(FreeMarkerDownloadView view) {
        FreeMarkerViewResolver resolver = new FreeMarkerViewResolver("", view.getFileNameExtension() + ".ftl");
        resolver.setCache(true);
        resolver.setContentType(view.getContentType());
        resolver.setExposeSpringMacroHelpers(true);
        resolver.setViewClass(view.getClass());
        return resolver;
    }

    @Bean
    public ViewResolver pdfViewResolver() {
        return makeViewResolver(new FreeMarkerPDFView());
    }

    @Bean
    public ViewResolver csvViewResolver() {
        return makeViewResolver(new FreeMarkerCSVView());
    }

    @Bean
    public ViewResolver txtViewResolver() {
        return makeViewResolver(new FreeMarkerTXTView());
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.viewResolver(radsStandardViewResolver());
        registry.viewResolver(csvViewResolver());
        registry.viewResolver(pdfViewResolver());
        registry.viewResolver(txtViewResolver());
        registry.enableContentNegotiation(new MappingJackson2JsonView());
    }

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorParameter(true)
            .defaultContentType(MediaType.TEXT_HTML)
            .mediaType("pdf", MediaType.APPLICATION_PDF)
            .mediaType("csv", new MediaType("application", "csv"))
            .mediaType("json", MediaType.APPLICATION_JSON)
            .mediaType("html", MediaType.TEXT_HTML)
            .mediaType("txt", MediaType.TEXT_PLAIN);
    }

    @Bean
    public MultipartResolver multipartResolver() {
        return new StandardServletMultipartResolver();
    }

}

Note that if we register SpringServletConfig in the root context, then the error goes away. However, this causes it to clash with the /rest DispatcherServlet and apply unwanted content negotiation settings to it.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions