Hi, Firstly, thank you for all the amazing work you do in CXF. I participate in the Apache TomEE project, which includes CXF to enable TomEE to provide REST and SOAP based services.
We've had a slightly unusual problem crop up that specifically affects applications that expose Jakarta REST endpoints (through the included CXF in TomEE), and include the Spring Framework in the application's WEB-INF/lib. The exception we see is: java.lang.NoClassDefFoundError: org/springframework/web/filter/ServerHttpObservationFilter at org.apache.cxf.jaxrs.springmvc.SpringWebUtils.setHttpRequestURI(SpringWebUtils.java:51) ~[cxf-rt-frontend-jaxrs-4.0.4.jar:4.0.4] at org.apache.cxf.jaxrs.utils.HttpUtils.setHttpRequestURI(HttpUtils.java:380) ~[cxf-rt-frontend-jaxrs-4.0.4.jar:4.0.4] at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.setExchangeProperties(JAXRSInInterceptor.java:246) ~[cxf-rt-frontend-jaxrs-4.0.4.jar:4.0.4] at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:183) ~[cxf-rt-frontend-jaxrs-4.0.4.jar:4.0.4] at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:78) ~[cxf-rt-frontend-jaxrs-4.0.4.jar:4.0.4] at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307) ~[cxf-core-4.0.4.jar:4.0.4] at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) ~[cxf-core-4.0.4.jar:4.0.4] at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:265) ~[cxf-rt-transports-http-4.0.4.jar:4.0.4] at org.apache.openejb.server.cxf.rs.CxfRsHttpListener.doInvoke(CxfRsHttpListener.java:266) ~[openejb-cxf-rs-9.1.3.jar:9.1.3] at org.apache.tomee.webservices.CXFJAXRSFilter.doFilter(CXFJAXRSFilter.java:99) ~[tomee-jaxrs-9.1.3.jar:9.1.3] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[catalina.jar:10.0.27] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[catalina.jar:10.0.27] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-websocket.jar:10.0.27] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[catalina.jar:10.0.27] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[catalina.jar:10.0.27] at org.apache.openejb.server.httpd.EEFilter.doFilter(EEFilter.java:67) ~[openejb-http-9.1.3.jar:9.1.3] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[catalina.jar:10.0.27] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[catalina.jar:10.0.27] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.0.19.jar:6.0.19] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.19.jar:6.0.19] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[catalina.jar:10.0.27] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[catalina.jar:10.0.27] at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.0.19.jar:6.0.19] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.19.jar:6.0.19] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[catalina.jar:10.0.27] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[catalina.jar:10.0.27] at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:124) ~[spring-boot-3.1.11.jar:3.1.11] at org.springframework.boot.web.servlet.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:99) ~[spring-boot-3.1.11.jar:3.1.11] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.19.jar:6.0.19] at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:117) ~[spring-boot-3.1.11.jar:3.1.11] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[catalina.jar:10.0.27] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[catalina.jar:10.0.27] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.0.19.jar:6.0.19] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.19.jar:6.0.19] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[catalina.jar:10.0.27] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[catalina.jar:10.0.27] at io.smallrye.metrics.jaxrs.JaxRsMetricsServletFilter.doFilter(JaxRsMetricsServletFilter.java:53) ~[smallrye-metrics-4.0.0.jar:na] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[catalina.jar:10.0.27] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[catalina.jar:10.0.27] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[catalina.jar:10.0.27] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[catalina.jar:10.0.27] at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:45) ~[tomee-catalina-9.1.3.jar:9.1.3] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[catalina.jar:10.0.27] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119) ~[catalina.jar:10.0.27] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[catalina.jar:10.0.27] at org.apache.tomee.catalina.OpenEJBSecurityListener$RequestCapturer.invoke(OpenEJBSecurityListener.java:97) ~[tomee-catalina-9.1.3.jar:9.1.3] at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690) ~[catalina.jar:10.0.27] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[catalina.jar:10.0.27] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:356) ~[catalina.jar:10.0.27] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-coyote.jar:10.0.27] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-coyote.jar:10.0.27] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:870) ~[tomcat-coyote.jar:10.0.27] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1762) ~[tomcat-coyote.jar:10.0.27] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-coyote.jar:10.0.27] at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-util.jar:10.0.27] at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-util.jar:10.0.27] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-util.jar:10.0.27] at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na] Caused by: java.lang.ClassNotFoundException: org.springframework.web.filter.ServerHttpObservationFilter at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445) ~[na:na] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:592) ~[na:na] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) ~[na:na] ... 58 common frames omitted It looks like org.apache.cxf.jaxrs.springmvc.SpringWebUtils checks whether Spring is present using the Thread Context Class Loader, which in the case of TomEE includes the application's classes and libraries, and TomEE's libraries (as a parent class loader). The setHttpRequestURI() method, however, uses the Class Loader that loaded org.apache.cxf.jaxrs.springmvc.SpringWebUtils (the parent class loader), so the Spring Framework included in the application is not visible at this point. I would imagine that if this were deployed in Tomcat, and both CXF and Spring were included in the application's WEB-INF/lib, this would not be an issue. We can mitigate this in TomEE by patching org.apache.cxf.jaxrs.springmvc.SpringWebUtils like this: https://github.com/apache/tomee/pull/1131/files - i.e. in setHttpRequestURI() invoke Spring using reflection, loading the necessary classes from the Thread Context Class Loader. This doesn't feel particularly elegant, however, and I wonder if there's a better fix that could be applied in CXF? If you have any thoughts, and would be willing to accept a change to help out with this, I'd be very happy to work on the change and provide a pull request. Many thanks Jon