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.
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 supportedwhen the matcher is used.To Reproduce
Visit any page post-login.
Expected behavior
Pages should load normally
Sample
Our web application initializer is configured with:
SpringCoreConfig.javamerely defines general application beans like the data layer.SpringSecurityConfig.javaincludes the relevant request matcher that triggers the exception:SpringServletConfig.javacontains:Note that if we register SpringServletConfig in the root context, then the error goes away. However, this causes it to clash with the
/restDispatcherServlet and apply unwanted content negotiation settings to it.