简体   繁体   中英

Java ServiceLoaders, Tomcat, Apache CXF and Metro

I have to get some information from an external SOAP web service using a web application deployed on Tomcat 7. This external web service requires TLS with mutual authentication.

As a starting point, I have installed Tomcat 7.0.96 in my desktop computer and, using the external web service wsdl file, I have put a dummy web service up, that mimmicks the real one, returning some hardcoded objects when queried. I have used Apache CXF 3.3.8.

I also have a web application that acts as a proxy for another web app, and as a client for the external (test and production), and dummy (local) web services.

Proxy web app requests objects from dummy web service. Mutual TLS authentication is assured using keystores present in CXF 3.3.8 samples. In my desktop computer, everything works fine, my dummy web service serves the objects as expected.

Problem arises when I ask to deploy the proxy web app on a test server that I do not control. This server runs Tomcat 7.0.76 over CentOS 7. When the proxy web app tries to create the external web service client, an exception throws:

java.lang.ClassCastException: com.sun.xml.ws.client.sei.SEIStub cannot be cast to org.apache.cxf.frontend.ClientProxy

I have searched for documentation about Java proxies and service loaders. Test server has three jaxws-xxx.jars in /tomcat/lib folder. AFAIK these jars are Metro web services API and implementation. I have a copy of these at my local tomcat/lib folder, and I can reproduce the problem.

I have included a Context.xml file in my proxy web app. Depending upon I include an Loader element in Context.xml, setting Loader attribute delegate to true or false, I am able to reproduce or solve the problem.

But when I deploy the proxy web app in test server, including Context.xml as explained, the aforementioned exception always arises.

I have included some lines in proxy web app printing to log implementation classes showed in ServiceLoader Java class iterator. At my local PC, com.sun.xml.ws.spi.Providerimpl appears before of after org.apache.cxf.jaxws.spi.ProviderImpl depending upon Loader "delegate" attribute value, as expected.

But using the same Context.xml webapp file, at the test server, sun's spi appears always before cxf's.

Has anybody faced this problem? Any suggestions? Thanks in advance

You should ask the external Tomcat admin, why did he include JAX-WS RI libraries in the common classloader. IMHO opinion they shouldn't be there, but in the applications that use it.

Nevertheless your application classloader should pick the CXF implementation of JAX-WS unless:

  • the <Host> container has deployXML="false" and it ignores the META-INF/context.xml file in your application. If this is the case you can copy it manually to $CATALINA_BASE/conf/<enginename>/<hostname>/<contextname>.xml
  • the $CATALINA_BASE/conf/context.xml has a <Loader> component with delegate="true" .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM