Inheritance problem in a Java/CXF/SOAP app?
I'm working on an application that uses cxf, the base of the app is a wsdl file and I'm having some trouble working with the inheritance.
I'll try to make a clear example (not exactly what I'm working on, but it should sum up the idea). In the type definition I have the following
<xsd:complexType name="Parent" abstract="true">
</xsd:complexType>
<xsd:complexType name="ChildA">
<xsd:complexContent>
<xsd:extension base="tns:Parent">
<xsd:sequence>
开发者_如何学Python <xsd:element name="attr1" type="xsd:double"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="ChildB">
<xsd:complexContent>
<xsd:extension base="tns:Parent">
<xsd:sequence>
<xsd:element name="attr2" type="xsd:double"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
When the java code is generated using wsdl2java, everything works fine, I can even see the extends on the generated Child(A|B) classes.
However, if I implement a method that takes, as an input parameter, an element of the Parent type
<xsd:element name="methodInput">
<xsd:complexType>
<xsd:sequence >
<xsd:element name="input" type="tns:Parent"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
when I invoke the method from the client side (using the javascript generated by cxf) with the following (RemoteControl is the object handling the SOAP exchange in the client side) call:
var childA=new __childA();
childA.setAttr1(100);
RemoteControl.method(childA);
On the java side I have the following error (the ...
are there to replace the exact lines that are all linked to either to cxf or to sun.xml):
org.apache.cxf.interceptor.Fault: Unmarshalling Error: Unable to create an instance of Parent
...
Caused by: javax.xml.bind.UnmarshalException
- with linked exception:
[javax.xml.bind.UnmarshalException: Unable to create an instance of Parent
- with linked exception:
[java.lang.InstantiationException]]
...
Caused by: javax.xml.bind.UnmarshalException: Unable to create an instance of Parent
- with linked exception:
[java.lang.InstantiationException]
...
Caused by: javax.xml.bind.UnmarshalException: Unable to create an instance of Parent
- with linked exception:
[java.lang.InstantiationException]
...
Caused by: java.lang.InstantiationException
...
However, if the declaration of the input parameter is
<xsd:element name="methodInput">
<xsd:complexType>
<xsd:sequence >
<xsd:element name="input" type="tns:childA"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
Everything is working fine.
So I'm wondering if it's possible to uses the Parent class as an input parameter. And if it is possible, what I'm missing in order to make that work.
Thanks.
Edit:
I didn't manage to get that working exactly like I wanted to, but I figured a way around. I just used some other options of the xml schema. Two of those seems to work depending of the context.
First using choices (for a few childs):
<xsd:element name="methodInput">
<xsd:complexType>
<xsd:choice >
<xsd:element name="inputA" type="tns:childA"/>
<xsd:element name="inputB" type="tns:childB"/>
</xsd:choice>
</xsd:complexType>
</xsd:element>
Secondly using any element (when there are numerous choices)
<xsd:element name="methodInput">
<xsd:complexType>
<xsd:sequence >
<xsd:any/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
But this one seems to ask for a little bit more of code on the server end.
P.S: <xsd:element name="methodInput" type="anyType" />
seems to produce an erroneous message on the client side, that's why I used a sequence.
I don't think the javascript clients support type inheritance at all. There are a bunch of restrictions on it. Patches would be welcome. :-)
In particular, the javascript would need to be updated to output an xsi:type="ns:Child1" attribute so JAXB can properly map it.
Looking at the error message, removing the abstract="true" from Parent could have solved the issue.
精彩评论