JAX-WS = When Apache CXF is installed it “steals” default JDK JAX-WS implementation, how to solve?

I have a strange problem.

  1. Using wsimport I generated als JAX-WS Code from a WSDL (in a dedicated eclipse java project). This works fine in JDK6 without any external dependencies (running in Eclipse)

  2. I have second project where I once used Apache CXF. If I copy the Code described in 1.) into this project, suddenly not the JDK executes the JAX-WS stuff (files I generated), but rather Apache CXF.

How can I prevent Apache CXF “running” the JAX-WS stuff. (Problem is, CXF Fails to run the code…). I also completely do not understand how Apache CXF discovers these classes. I did not register them anywere?

Thank you very much! Markus

CXF JAXWS and JAXB jar files

Learning about webservices using apache CXF. Included CXF-api and JAXB-api jar files in the project. Do I have to include JAXWS-api jar also.

EasyMock CXF JAXWS Client

I am trying to test my web service client which uses CXF with JAXWS annotations i.e. @WebService and @SOAPBinding. I was wondering is there a way to mock the interface which has these annotations? If

How to use Apache CXF as client?

I know how to generate client stubs using Apache CXF. However, when I try to run the generated classes, it uses JAXWS. Also, I notice that the import classes of the generated classes are from the java

How do JAXWS async calls work with polling

I need to invoke a long running task via a SOAP web service, using JAXWS on both ends, specifically, Apache CXF 2.6 on both ends. I see that I can enable async methods in the CXF code generator, which

Parser Error cxf-beans.xml no declaration can be found for element ‘jaxws:endpoint’

<?xml version=1.0 encoding=UTF-8?> <beans xmlns=http://www.springframework.org/schema/beans xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:jaxws=http://cxf.apache.org/jaxw

spring webservice Invalid NamespaceHandler problem (jaxws)

I am building a web service with spring. I can build and deploy the project to tomcat but when the server starts up I am getting following error: Invalid NamespaceHandler class [org.apache.cxf.jaxws.

JAXWS — how to change the endpoint address

How can I dynamically change the address which my JAXWS client is using? This client was generated by wsimport.

JaxWS ClassCastException on JBoss

I’m using JBoss 5.1.0.GA (for JDK6), and jaxws 2.2.6. When I invoke the webservice, I get the following exception: java.util.ServiceConfigurationError: javax.xml.ws.spi.Provider: Provider org.jboss.w

Unable to locate Spring NamespaceHandler for XML schema namespace [http://cxf.apache.org/jaxws]

I need to integrate Spring with CXF version 3.0. CXF libraries are in the classpath. I am getting the error Unable to locate Spring NamespaceHandler for XML schema namespace [http://cxf.apache.org/ja

Changing the default XML namespace prefix generated with JAXWS

I am using JAXWS to generate a WebService client for a Java Application we’re building. When JAXWS build its XMLs to use in SOAP protocol, it generates the following namespace prefix: <env:Envelope

Answers

Apache CXF (cxf-rt-frontend-jaxws-*.jar to be precise) registers itself 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 javax.xml.ws.spi.FactoryFinder#find method you will discover that JDK searches the CLASSPATH for the presence of javax.xml.ws.spi.Provider file and falls back to default Sun implementation if not available. So you have two options to force fallback:

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

  • or override javax.xml.ws.spi.Provider file provided by CXF to point to fallback location

The second option is actually a bit easier. Simply create:

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

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

org.apache.cxf.jaxws.spi.ProviderImpl

That’s it, tested with javax.xml.ws.Endpoint#publish.

For the default implementation put:

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

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

I have an EAR file and my jaxws client jar stays inside it under APP-INF/lib

I want jdk libraries to be used for jaxws service however since this EAR file has cxf-rt-frontend-jaxws-3.0.2.jar hence javax.xml.ws.spi.Provider is always loaded by org.apache.cxf.jaxws22.spi.ProviderImpl

cxf-rt-frontend-jaxws-3.0.2.jar has javax.xml.ws.spi.Provider file inside it’s META-INF/services folder with an entry org.apache.cxf.jaxws22.spi.ProviderImpl

I want to over write this one and for that I did following:

  1. I added javax.xml.ws.spi.Provider with an entry com.sun.xml.internal.ws.spi.ProviderImpl under META-INF/services of my client jar
  2. I also added META-INF/services with same file/content directly under EAR’s META-INF too
  3. I also added following as in server start property -Djavax.xml.ws.spi.Provider=com.sun.xml.internal.ws.spi.ProviderImpl

No matter what i try it’s always that cxf-rt-frontend-jaxws-3.0.2.jar that takes precedence, please help.

I tried the other and I just couldn’t make it work at all, so to set CXF if it was not set to 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();

The standard finding mechanisms don’t seem to work nicely in OSGi (*).

There are two ways I’ve gotten to work forcing the service to pick up the CXF implementation of javax.xml.ws.spi.Provider:

  • the approach of setting delegate by reflection given in EpicPandaForce’s answer to this question (http://stackoverflow.com/a/31892305/109079)

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

Here is an example of the latter, for less intrepid coders who prefer not reflectively 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 couple of notes:

  • Passing a URL as above, rather than the simpler factory.setWsdlURL(String) may be needed if the WSDL is a resource on the classpath (avoid unresolvable bundle://… URLs for classpath items)

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


(*) As for why the finding mechanisms don’t work in most OSGi containers, check out this little bit of nasty in Oracle Java’s 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 indeed!