JAX-WS = When Apache CXF is installed, it "steals" the standard JAX-WS JDK default implementation, how to solve it?

I have a strange problem.

  • Using wsimport, I generated JAX-WS code from WSDL (in a special project of the eclipse java project). This works fine in JDK6 without any external dependencies (works in Eclipse)

  • I have a second project in which I once used Apache CXF. If I copy the code described in 1.) to this project, suddenly the JDK does not execute JAX-WS (the files that I generated), but Apache CXF.

How can I prevent Apache CXF from running JAX-WS. (The problem is that CXF does not work to run the code ...). I also don't completely understand how Apache CXF detects these classes. I have not registered them?

Thank you very much! Marcus

+26
java web-services jax-ws cxf
Jun 15 2018-11-11T00:
source share
5 answers

Apache CXF ( cxf-rt-frontend-jaxws-*.jar , to be precise) is registered as a JAX-WS provider in the JVM. Inside the aforementioned JAR, there is a file named: /META-INF/services/javax.xml.ws.spi.Provider with the following contents:

 org.apache.cxf.jaxws.spi.ProviderImpl 

If you now look at the javax.xml.ws.spi.FactoryFinder#find method, you will find that the JDK looks for CLASSPATH for the javax.xml.ws.spi.Provider file and returns to the default Sun implementation if it is not available. Thus, you have two options for pushing back:

  • either remove cxf-rt-frontend-jaxws-*.jar from CLASSPATH

  • or override the javax.xml.ws.spi.Provider file provided by CXF to indicate the backup location

The second option is actually a little easier. Just create:

 /src/main/resources/META-INF/services/javax.xml.ws.spi.Provider 

(assuming you are using Maven) with the following contents:

 org.apache.cxf.jaxws.spi.ProviderImpl 

This is it, tested with javax.xml.ws.Endpoint#publish .

+49
Jun 15 2018-11-11T00:
source share

For the default implementation, put:

 com.sun.xml.internal.ws.spi.ProviderImpl 

inside / src / main / resources / META-INF / services / javax.xml.ws.spi.Provider

+13
Jul 30 '13 at 9:15
source share

I tried another one, and I just couldn't get it to work at all, so to install CXF, if it was not installed in CXF, I just override the delegate inside the service.

  try { loc = this.getClass().getResource(wsdlResource); QName qName = new QName( wsTargetNamespace, wsName ); service = new YourWS(loc, qName); Field delegateField = Service.class.getDeclaredField("delegate"); //ALLOW CXF SPECIFIC SERVICE DELEGATE ONLY! delegateField.setAccessible(true); ServiceDelegate previousDelegate = (ServiceDelegate) delegateField.get(service); if (!previousDelegate.getClass().getName().contains("cxf")) { ServiceDelegate serviceDelegate = ((Provider) Class.forName("org.apache.cxf.jaxws.spi.ProviderImpl").newInstance()) .createServiceDelegate(loc, qName, service.getClass()); log.info("The " + getClass().getSimpleName() + " delegate is changed from " + "[" + previousDelegate + "] to [" + serviceDelegate + "]"); delegateField.set(service, serviceDelegate); } port = service.getYourWSSoap(); 
+5
Aug 08 '15 at 10:50
source share

Standard search engines do not work well in OSGi (*).

There are two ways to get a service to pick up a CXF implementation of javax.xml.ws.spi.Provider :

  • the delegate installation approach by reflection given in EpicPandaForce answers this question ( stack overflow

  • lower level JaxWsProxyFactoryBean ; this seems to avoid all the javax.xml.ws.spi.FactoryFinder calls included in Java, which is the root of the problem.

Here is an example of the latter, for less fearless coders who prefer not to reflect changing private fields:

 JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.getClientFactoryBean().getServiceFactory().setWsdlURL(WinRmService.WSDL_LOCATION); factory.setServiceName(WinRmService.SERVICE); factory.setEndpointName(WinRmService.WinRmPort); // factory.setFeatures(...); // if required Service winrm = factory.create(WinRm.class); Client client = ClientProxy.getClient(winrm); 

A few notes:

  • Passing the URL as above, rather than a simple factory.setWsdlURL(String) may be required if WSDL is a resource in the classpath (avoid unresolvable bundle://... URLs for pathpath elements)

  • You may need additional packages for features (such as addressing)




(*) Regarding why search engines do not work in most OSGi containers, check out this little bit annoying in Oracle Java FactoryFinder :

 private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "com.sun.org.glassfish.hk2.osgiresourcelocator.ServiceLoader"; private static boolean isOsgi() { try { Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME); return true; } catch (ClassNotFoundException ignored) { } return false; } 

OSGi = Glassfish? Fishy really!

+2
Aug 31 '16 at 14:00
source share

I had a similar problem. In my case, I had to use org.apache.cxf.jaxws.spi.ProviderImpl for JAX-WS stuff (creating webservice endpoints, etc.) and com.sun.xml.internal.ws.spi.ProviderImpl to publish the end points at com.sun.net.httpserver.HttpsServer .

I managed to solve this problem by creating my own provider, which extends javax.xml.ws.spi.Provider and uses it instead of the standard one.

 package provider; import java.net.URL; import java.util.List; import javax.xml.namespace.QName; import javax.xml.transform.Source; import javax.xml.ws.Endpoint; import javax.xml.ws.EndpointReference; import javax.xml.ws.WebServiceFeature; import javax.xml.ws.spi.Provider; import javax.xml.ws.spi.ServiceDelegate; import javax.xml.ws.wsaddressing.W3CEndpointReference; import org.w3c.dom.Element; public class MyProvider extends Provider { @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public ServiceDelegate createServiceDelegate(URL wsdlDocumentLocation, QName serviceName, Class serviceClass) { try { return ((Provider) Class.forName("org.apache.cxf.jaxws.spi.ProviderImpl").newInstance()).createServiceDelegate(wsdlDocumentLocation, serviceName, serviceClass.getClass()); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public Endpoint createEndpoint(String bindingId, Object implementor) { try { return ((Provider) Class.forName("com.sun.xml.internal.ws.spi.ProviderImpl").newInstance()).createEndpoint(bindingId, implementor); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public Endpoint createAndPublishEndpoint(String address, Object implementor) { try { return ((Provider) Class.forName("com.sun.xml.internal.ws.spi.ProviderImpl").newInstance()).createAndPublishEndpoint(address, implementor); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public EndpointReference readEndpointReference(Source eprInfoset) { try { return ((Provider) Class.forName("org.apache.cxf.jaxws.spi.ProviderImpl").newInstance()).readEndpointReference(eprInfoset); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public <T> T getPort(EndpointReference endpointReference, Class<T> serviceEndpointInterface, WebServiceFeature... features) { try { return ((Provider) Class.forName("org.apache.cxf.jaxws.spi.ProviderImpl").newInstance()).getPort(endpointReference, serviceEndpointInterface, features); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public W3CEndpointReference createW3CEndpointReference(String address, QName serviceName, QName portName, List<Element> metadata, String wsdlDocumentLocation, List<Element> referenceParameters) { try { return ((Provider) Class.forName("org.apache.cxf.jaxws.spi.ProviderImpl").newInstance()).createW3CEndpointReference(address, serviceName, portName, metadata, wsdlDocumentLocation, referenceParameters); } catch (Exception e) { e.printStackTrace(); } return null; } } 

Then just create:

 /src/main/resources/META-INF/services/javax.xml.ws.spi.Provider 

(assuming you are using Maven) with the following contents:

 package.MyProvider 
0
Dec 13 '17 at 13:21
source share



All Articles