Thanks Andriy and Romain for your replies.

> This is quite an interesting issue, is it possible to share (or point out
to an example) small reproducer project for this problem?

Yes - here's a reproducer: https://github.com/jgallimore/demo

If you clone this and run mvn clean install tomee:run, it will boot up a
TomEE 9.1.3 (which includes CXF 4.0.4). If you invoke a GET
http://localhost:8080/hello you'll see the error on the console.

> * openejb.cxf.CxfContainerClassLoader is false

This didn't work.

> * cxf is in the webapp, tomee cxf services disabled and cxf packages
"forced-load"

I haven't tried this. As I noted in the original email, 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. I suspect
this would essentially give the same setup and I would imagine it would
work, but I would expect we'd lose the integration functionality in TomEE
(which we run the TCK against). Its also a big ask ask for anyone using
JAX-RS services, and just so happens to have Spring in their application,
as this did work ok in TomEE 9.1.2 (CXF 4.0.3).

> If not it can just be to detect it in tomee and setup the webapp properly?

Can you give me some pointers on what you mean here? I'm happy to make
adjustments in TomEE, and equally happy to work on a suitable update for
CXF if preferred.

Many thanks!

Jon

On Fri, May 17, 2024 at 3:56 AM Romain Manni-Bucau <rmannibu...@gmail.com>
wrote:

> Hi Jon,
>
> Does it happen in the following both cases:
>
> * openejb.cxf.CxfContainerClassLoader is false
> * cxf is in the webapp, tomee cxf services disabled and cxf packages
> "forced-load"
>
> ?
>
> If not it can just be to detect it in tomee and setup the webapp properly?
>
> Le jeu. 16 mai 2024 à 23:25, Andriy Redko <drr...@gmail.com> a écrit :
>
>> Hey Jonathan,
>>
>> This is quite an interesting issue, is it possible to share (or point out
>> to an example) small reproducer project for this problem? I think I
>> understand
>> what is happening but don't have a clear fix for that to suggest at the
>> moment.
>>
>> Thank you.
>>
>> Best Regards,
>>     Andriy Redko
>>
>> > 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
>>
>>

Reply via email to