Hi Chris Spring's ObservationFilterChainDecorator is ridiculous, isn't it?
> What if you create an empty jaxp.properties file and make it available to the > common ClassLoader (e.g. in lib/empty-jaxp.jar:/jaxp.properties) -- does that > prevent the problem? I think that boils down to what I'm already doing with the system property, getting to the FactoryFinder before it uses findServiceProvider(). Haven't tried it, but I'm sure it would work. imho, Tomcat's EncodingDetector should init with either XML_INPUT_FACTORY = XMLInputFactory.newDefaultFactory(); to just always use the JVM XMLInputFactory, or then XML_INPUT_FACTORY = XMLInputFactory.newFactory(XMLInputFactory.class.getName(), EncodingDetector.class.getClassLoader()); to honor it's own classloader (maybe EncodingDetector.class.getClassLoader() is the wrong approach, basically something getTomcatCommonClassloader()) What I just don't get is why there's so little online about others havingEncodingDetector similar issues. Spring + libs like CXF or jackson-dataformat-xml are common, both those libs have transitive dependencies on woodstox-core. Throw in ehcache, also common, and your webapp won't undeploy if it's the first webapp to load a JSP and thus clinit EncodingDetector. Maybe the public has just given up on clean undeploying. Simon Mühlegasse 18, 6340 Baar, Switzerland https://www.want.ch https://www.funnel.travel On Wed, Mar 20, 2024 at 7:01 PM Christopher Schultz <[email protected]> wrote: > > Simon, > > On 3/20/24 09:59, Simon Niederberger wrote: > > The whole thing is caused by Maven dependencies which pull in > > com.fasterxml.woodstox:woodstox-core. The WstxInputFactory has a > > > > @ServiceProvider(XMLInputFactory.class) > > > > annotation, where ServiceProvider is > > org.ehcache.spi.service.ServiceProvider. I didn't manage to trace the > > key code section, but I do find that the > > javax.xml.stream.FactoryFinder then ends up finding WstxInputFactory > > as registered service provider. As WstxInputFactory is not on the > > common classpath (it's in WEB-INF/lib), I assume it's the webapp > > classloader which is used. Below is the stacktrace where > > EncodingDetector clinit happens (I defined a > > ch.want.funnel.FunnelApp$DelegatingXMLInputFactory to get > > stacktraces): > > > > Currently I'm setting > > > > System.setProperty("javax.xml.stream.XMLInputFactory", > > "com.sun.xml.internal.stream.XMLInputFactoryImpl"); > > to get a XMLInputFactory implementation which is on the common > > loader's classpath, so the webapp can be undeployed cleanly. > > So this works, right? > > What if you create an empty jaxp.properties file and make it available > to the common ClassLoader (e.g. in lib/empty-jaxp.jar:/jaxp.properties) > -- does that prevent the problem? > > I'm wondering if Tomcat should simply ship with an empty jaxp.properties > file to prevent this kind of thing from happening by default. If someone > wants to bundle an XMLInputFactory into Tomcat's lib/ directory and use > that, they could remove this file. > > BTW that's an impressive stack trace. ;) > > -chris > > > java.lang.RuntimeException: Stracktrace for tracking XMLInputFactory > > creation > > at > > ch.want.funnel.FunnelApp$DelegatingXMLInputFactory.<init>(FunnelApp.java:107) > > at > > java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native > > Method) > > at > > java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77) > > at > > java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) > > at > > java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) > > at > > java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480) > > at > > java.xml/javax.xml.stream.FactoryFinder.newInstance(FactoryFinder.java:190) > > at > > java.xml/javax.xml.stream.FactoryFinder.newInstance(FactoryFinder.java:148) > > at > > java.xml/javax.xml.stream.FactoryFinder.find(FactoryFinder.java:261) > > at > > java.xml/javax.xml.stream.FactoryFinder.find(FactoryFinder.java:223) > > at > > java.xml/javax.xml.stream.XMLInputFactory.newInstance(XMLInputFactory.java:166) > > at > > org.apache.jasper.compiler.EncodingDetector.<clinit>(EncodingDetector.java:38) > > at > > org.apache.jasper.compiler.ParserController.determineSyntaxAndEncoding(ParserController.java:324) > > at > > org.apache.jasper.compiler.ParserController.doParse(ParserController.java:201) > > at > > org.apache.jasper.compiler.ParserController.parseDirectives(ParserController.java:128) > > at > > org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:207) > > at org.apache.jasper.compiler.Compiler.compile(Compiler.java:396) > > at org.apache.jasper.compiler.Compiler.compile(Compiler.java:372) > > at org.apache.jasper.compiler.Compiler.compile(Compiler.java:356) > > at > > org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:603) > > at > > org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:396) > > at > > org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:380) > > at > > org.apache.jasper.servlet.JspServlet.service(JspServlet.java:328) > > at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) > > at > > org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:479) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:340) > > at > > org.springframework.security.web.ObservationFilterChainDecorator.lambda$wrapSecured$0(ObservationFilterChainDecorator.java:82) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:128) > > at > > org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:100) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126) > > at > > org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:91) > > at > > org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227) > > at > > org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:75) > > at > > org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$0(ObservationFilterChainDecorator.java:323) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:224) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233) > > at > > org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:186) > > at > > org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:113) > > at > > org.springframework.web.servlet.handler.HandlerMappingIntrospector.lambda$createCacheFilter$3(HandlerMappingIntrospector.java:195) > > 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.WebMvcSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebMvcSecurityConfiguration.java:225) > > at > > org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:352) > > at > > org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:268) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:642) > > at > > org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:408) > > at > > org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:340) > > at > > org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:277) > > at > > org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequestDispatcher.forward(HeaderWriterFilter.java:170) > > at > > org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:171) > > at > > org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:314) > > at > > org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1431) > > at > > org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1167) > > 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:564) > > at > > org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) > > at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.springframework.web.filter.AbstractRequestLoggingFilter.doFilterInternal(AbstractRequestLoggingFilter.java:289) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108) > > at > > org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:479) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:340) > > at > > org.springframework.security.web.ObservationFilterChainDecorator.lambda$wrapSecured$0(ObservationFilterChainDecorator.java:82) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:128) > > at > > org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:100) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126) > > at > > org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131) > > at > > org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227) > > at > > org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > at > > org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > 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.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > 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.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > 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.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > 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.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$0(ObservationFilterChainDecorator.java:323) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:224) > > at > > org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137) > > 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.servlet.handler.HandlerMappingIntrospector.lambda$createCacheFilter$3(HandlerMappingIntrospector.java:195) > > 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.WebMvcSecurityConfiguration$CompositeFilterChainProxy.doFilter(WebMvcSecurityConfiguration.java:225) > > at > > org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:352) > > at > > org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:268) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:109) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:124) > > at > > org.springframework.boot.web.servlet.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:99) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) > > at > > org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:117) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) > > at > > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) > > at > > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) > > at > > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) > > at > > org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) > > at > > org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) > > at > > org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) > > at > > org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) > > at > > org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) > > at > > org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:673) > > at > > org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) > > at > > org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) > > at > > org.apache.coyote.ajp.AjpProcessor.service(AjpProcessor.java:431) > > at > > org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) > > at > > org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896) > > at > > org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744) > > at > > org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) > > at > > org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) > > at > > org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) > > at > > org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) > > at java.base/java.lang.Thread.run(Thread.java:840) > > > > > > Mühlegasse 18, 6340 Baar, Switzerland > > > > https://www.want.ch > > > > https://www.funnel.travel > > > > > > > > > > > > On Tue, Mar 19, 2024 at 12:31 PM Christopher Schultz > > <[email protected]> wrote: > >> > >> Simon, > >> > >> On 3/18/24 15:17, Simon Niederberger wrote: > >>> I'm analyzing a memory leak reported by Tomcat, and have narrowed it > >>> down to org.apache.jasper.compiler.EncodingDetector: > >>> > >>> private static final XMLInputFactory XML_INPUT_FACTORY; > >>> static { > >>> XML_INPUT_FACTORY = XMLInputFactory.newInstance(); > >>> } > >>> > >>> This class is called by webapp code on a GET request > >>> > >>> at > >>> org.apache.jasper.compiler.EncodingDetector.<clinit>(EncodingDetector.java:38) > >>> at > >>> org.apache.jasper.compiler.ParserController.determineSyntaxAndEncoding(ParserController.java:324) > >>> at > >>> org.apache.jasper.compiler.ParserController.doParse(ParserController.java:201) > >>> at > >>> org.apache.jasper.compiler.ParserController.parseDirectives(ParserController.java:128) > >>> at > >>> org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:207) > >>> ... > >>> at > >>> org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:396) > >>> at > >>> org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:380) > >>> at > >>> org.apache.jasper.servlet.JspServlet.service(JspServlet.java:328) > >>> at > >>> jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) > >>> > >>> The EncodingDetector class, if not yet loaded, will be loaded in the > >>> common classloader, then continue by loading the XMLInputFactory using > >>> the webapp context, and might end up with a XMLInputFactory > >>> implementation from a webapp-provided JAR. If that happens, the webapp > >>> can't undeploy. (In my case, woodstox WstxInputFactory registers > >>> itself as ServiceProvider for XMLInputFactory) > >>> > >>> For completeness: javax.xml.stream.FactoryFinder.findServiceProvider() > >>> is called without classloader (cl = null), and has > >>> > >>> if (cl == null) { > >>> //the current thread's context class loader > >>> serviceLoader = ServiceLoader.load(type); > >>> } else { > >>> serviceLoader = ServiceLoader.load(type, cl); > >>> } > >>> > >>> I can't find anything online about memory leaks from webapp-provided > >>> XMLInputFactory implementations, but this must be fairly common. Is my > >>> understanding correct, or have I mis-configured something? (I'm mainly > >>> wondering whether any XMLInputFactory-implementing JARs belong in > >>> tomcat/lib, but again I'm not finding anything online confirming that) > >>> > >>> Tomcat 10.1.19 > >>> JVM 17.0.10+7-Ubuntu-120.04.1 > >>> Ubuntu 20.04.6 LTS > >> > >> I'm not sure how many web applications ship with an XMLInputSource, but > >> they definitely do exist. I'm fairly sure most applications won't set a > >> system property or ship with a stax.properties/jaxp.properties file to > >> override the default implementation, but of course if it's possible, > >> someone will eventually do it. > >> > >> I'm curious: in your example, how are you declaring your implementation > >> class, and which implementation are you using? > >> > >> Are you able to log in EncodingDetector.<clinit> what the value of the > >> thread's context classloader is? I would expect that it's using the > >> common classloader, as you say, and that the implementation class would > >> also be loaded using that same classloader. > >> > >> -chris > >> > >> --------------------------------------------------------------------- > >> To unsubscribe, e-mail: [email protected] > >> For additional commands, e-mail: [email protected] > >> > > > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: [email protected] > > For additional commands, e-mail: [email protected] > > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [email protected] > For additional commands, e-mail: [email protected] > --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
