RKodakandla
RKodakandla

Reputation: 3484

ClassCastException with JAXB - Websphere jar vs applicationl jar

I'm getting a class cast exception when trying to marhsal Java object into a string. I've included JAXB-2.1 jar in my lib folder. When deploying to WAS, I've changed the classloader strategy to parent last so that the jar in my local library will be picked up first. But this is still throwing classcast exception with the following message. What is the reason for this error?

javax.xml.bind.JAXBException: ClassCastException: attempting to cast jar:file:/opt/was7/base/crm/java/jre/lib/rt.jar!/javax/xml/bind/JAXBContext.class to wsjar:file:/prod/wesadm/wes/was7/base/profiles/sadasd/installedApps/asdadad/myapp.ear/myapp_war.war/WEB-INF/lib/jaxb-api-2.1.jar!/javax/xml/bind/JAXBContext.class.  Please make sure that you are specifying the proper ClassLoader.
        at javax.xml.bind.ContextFinder.handleClassCastException(ContextFinder.java:96)
        at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:214)
        at javax.xml.bind.ContextFinder.find(ContextFinder.java:372)
        at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574)
        at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:522)
        at com.my.MyClass.convertObjectToXML()

This is the convertObjectToXML() method.

private <T> String convertObjectToXMLString(T obj) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(obj.getClass());
        Marshaller marshaller = jaxbContext.createMarshaller();

        StringWriter sw = new StringWriter();
        marshaller.marshal(obj, sw);

        return sw.toString();

    }

This logic works fine when deployed to Tomcat. I'm unable to figure out why WAS jars are being picked up even though I mentioned the class loader as parent last.

Upvotes: 2

Views: 7163

Answers (3)

Sharad Gaikwad
Sharad Gaikwad

Reputation: 56

I was getting below exception while migrating app to Websphere 9.

java.lang.Exception: javax.xml.bind.JAXBException: ClassCastException: attempting to cast jar:file:/D:/WebSphere/AppServer/endorsed_apis/jaxb-api.jar!/javax/xml/bind/JAXBContext.class to wsjar:file:/D:/sites/XXXX.ear/Web.war/WEB-INF/lib/jaxb-api-2.2.10.jar!/javax/xml/bind/JAXBContext.class.  Please make sure that you are specifying the proper ClassLoader.    

I excluded all the references of the jars from application which are part of IBM jdk now. e.g. stax-api

    <dependency>
        <groupId>org.apache.xmlbeans</groupId>
        <artifactId>xmlbeans</artifactId>
        <version>2.6.0</version> 
        <exclusions>
            <exclusion>
                <groupId>stax</groupId>
                <artifactId>stax-api</artifactId>
            </exclusion>
            <exclusion>
                <groupId>xml-apis</groupId>
                <artifactId>xml-apis</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

Upvotes: 1

Beck Yang
Beck Yang

Reputation: 3024

The javax.xml.bind.ContextFinder.find(Class[] classes, Map properties) will look for jaxb.property first. If not found, it try to search/create a factory in following sequence:

  1. System property javax.xml.bind.context.factory
  2. Lookup using OSGi ServiceLoader
  3. Search META-INF services

I believe your program does not offer jaxb.property in package com.my. So the factory class is loading from Websphere JDK/library, it will return a object of JAXBContext class. But that class is different than the one in your WAR, so javax.xml.bind.ContextFinder throw ClassCastException.

Upvotes: 0

titou10
titou10

Reputation: 2977

It seems you bundled the JAXB api jars with your app. remove them from your app and it will work. Those jars are already bundled with WebSphere (in fact they are part of the JRE) and it causes classloader exception because two versions of the same classes are present

Upvotes: 1

Related Questions