Search code examples
javacxf

How to fix java.lang.IncompatibleClassChangeError: Implementing class with cxf


We are having an issue making a SOAP client call on tomcat 8 in a RedHat linux environment running openjdk version "1.8.0_201", while the same call works fine with a similar config on a Windows machine (tomcat 8, Oracle java 8) and AIX (Oracle java 8, tomcat 7).

Here is the stacktrace:

java.lang.IncompatibleClassChangeError: Implementing class
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2401)
        at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:859)
        at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1333)
        at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1185)
        at org.apache.cxf.ws.addressing.impl.AddressingFeatureApplier.initializeProvider(AddressingFeatureApplier.java:36)
        at org.apache.cxf.ws.addressing.WSAddressingFeature.initializeProvider(WSAddressingFeature.java:46)
        at org.apache.cxf.feature.AbstractFeature.initialize(AbstractFeature.java:49)
        at org.apache.cxf.frontend.ClientFactoryBean.applyFeatures(ClientFactoryBean.java:112)
        at org.apache.cxf.frontend.ClientFactoryBean.create(ClientFactoryBean.java:100)
        at org.apache.cxf.frontend.ClientProxyFactoryBean.create(ClientProxyFactoryBean.java:157)
        at org.apache.cxf.jaxws.JaxWsProxyFactoryBean.create(JaxWsProxyFactoryBean.java:142)
        at org.apache.cxf.jaxws.ServiceImpl.createPort(ServiceImpl.java:476)
        at org.apache.cxf.jaxws.ServiceImpl.getPort(ServiceImpl.java:343)
        at javax.xml.ws.Service.getPort(Service.java:160)

Using cxf version 2.7.18

pom.xml snippet

      <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxws</artifactId>
        <version>${cxf.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http-jetty</artifactId>
        <version>${cxf.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http</artifactId>
        <version>${cxf.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-rs-client</artifactId>
        <version>3.0.16</version>
      </dependency>

Solution

  • An IncompatibleClassChangeError happens because some code was compiled against one version of an API, but at runtime an incompatible version of the API is being loaded.

    (In this case, the "Implementing class" incompatibility means that a class has been declared as implements Something, but at runtime the Something turns out to be a class rather than an interface. This API change is not allowed.)

    The problem is that the stacktrace you have included doesn't tell us what class the incompatibility occurs in, and what it is incompatible with. The only real clue is that CXF appears to be loading an "provider"

    So what is the solution?

    There is no silver bullet. You will need to do some digging to find out what the actual problem is:

    1. Check the logs where you got the stacktrace from for other log messages that may tell you what was being loaded.
    2. Check the versions of the various CXF JAR files on the runtime platform.
    3. Check that you don't have different versions of the JARs in the webapp itself and in Tomcat's shared library directories.
    4. Modify Tomcat logging configs to set up logging level for the org.apache.catalina.loader package to DEBUG. This will log the JAR file that each class is loaded from.