Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB classes from Webservice marshalling error

Tags:

java

jaxb

jax-ws

I have some wsimport generated JAXB classes

wsimport -d src/main/java -keep -extension
  -p my.package
  http://www.OpenLigaDB.de/Webservices/Sportsdata.asmx?WSDL

I will demonstrate the problem with this class (only the @XmlRootElement was added by myself):

package my.package;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Sport", propOrder = {"sportsID","sportsName"})
@XmlRootElement(name = "sport")   //Added by myself
public class Sport
{
    protected int sportsID;
    protected String sportsName;

    public int getSportsID() {return sportsID;}
    public void setSportsID(int value) {this.sportsID = value;}

    public String getSportsName() {return sportsName;}
    public void setSportsName(String value) {this.sportsName = value;}
}

Direcly instantiating and marshalling works fine (Example1)

Sport sport = new Sport();
sport.setSportsID(1);
sport.setSportsName("test");

JAXBContext jc = JAXBContext.newInstance(Sport.class);
jc.createMarshaller().marshal(sport,System.out);

Now lets create the object inside a webservice call:

SportsdataSoap s = new Sportsdata().getSportsdataSoap();
ArrayOfSport sports = s.getAvailSports();

for(Sport sport : sports.getSport())
{
    JAXBContext jc = JAXBContext.newInstance(Sport.class);
    jc.createMarshaller().marshal(sport,System.out);
}

Then I got this exception:

Exception in thread "main" java.lang.ClassCastException: my.package.Sport$JaxbAccessorF_sportsID cannot be cast to com.sun.xml.bind.v2.runtime.reflect.Accessor
    at com.sun.xml.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory.instanciate(OptimizedAccessorFactory.java:199)
    at com.sun.xml.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory.get(OptimizedAccessorFactory.java:191)
    at com.sun.xml.bind.v2.runtime.reflect.Accessor$FieldReflection.optimize(Accessor.java:282)
    at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.<init>(SingleElementNodeProperty.java:94)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.sun.xml.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:128)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:183)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:526)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:341)
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1158)
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:140)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:202)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:363)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:522)
    at my.package.TestOpenLiga.testDisciplines(TestOpenLiga.java:48)
    at my.package.TestOpenLiga.main(TestOpenLiga.java:130)

How to deal with this? Thank you, Thor.

Update 2 If I modify Example1 to this, I get the same error

SportsdataSoap s = new Sportsdata().getSportsdataSoap();

Sport sport = new Sport();
sport.setSportsID(1);
sport.setSportsName("test");

JAXBContext jc = JAXBContext.newInstance(Sport.class);
jc.createMarshaller().marshal(sport,System.out);

Update 2 XML structure of sport

<Sport>
  <sportsID>int</sportsID>
  <sportsName>string</sportsName>
</Sport>
like image 274
Thor Avatar asked May 25 '11 11:05

Thor


3 Answers

I am not sure if this is the only reason why this could happen, but this is one problem I faced and solved like this, check your Java endorsed dir and removed any duplicate jaxb-impl.jar. This could happen even with webservice-api.jar. Hope this helps.

like image 106
Teja Kantamneni Avatar answered Nov 06 '22 23:11

Teja Kantamneni


I got the same error message recently when I tried to upgrade JAXB to a newer version than what came with the JDK. I had an external version of JAXB, but my JAX-WS was still the internal version that came with the JDK. The internal JAX-WS tried calling the internal JAXB, but the application wanted to use the external JAXB.

Essentially, both JAXB and JAX-WS have to be internal or both have to be external. This thread has advice if you have an external JAXB and you want to switch to using the internal version.

like image 32
Ritzbot Avatar answered Nov 06 '22 23:11

Ritzbot


I know, this question is old, but I just had a similar issue and I wanted to provide my solution to the problem here.

The issue was, that we had our own instance of a jaxbcontext in the same classloader as the jws JAXB context was residing in.

Thus, we added class A in our JAXB context and jws did add class A in his JAXB context.

On using the jws code, the classloader did provide the wrong class, and a classcast exception was thrown.

By using the JAXB.(un)marshal functions for this "shared" object, we could solve the issue.

UPDATE: Ok, since two asked, I will update this question after 4 years :-)

The issue described above points to a hierarchical classloader issue. JAXB generates class (un)marshalling objects on the fly from annotations and adds them to his cache. These classes seem to be identical at first but they are different class objects for the same annotations. This works because they are not in the same classloader and the servers classloader will not dive down the classloader tree to the other classloader to find them.

When we mixed up the objects from the lower classloader with the classloader higher up the hierarchy, the marshalling was unable to make a match.

Thats how I remember the issue.

like image 21
thst Avatar answered Nov 06 '22 22:11

thst