Ok I have managed to create a simple example of the behavior. Please note that I am pretty new to webservices and JBossWS (started using it a few days ago) so sorry if something is overly complicated. Feedback is highly appreciated.
I am using JBoss 4.2.0.GA and java version "1.5.0_08"
I started with the following WSDL (I have modified an echo tutorial I found on the web so please dont be confused by the namespace and other irregularities):
<?xml version="1.0" encoding="UTF-8"?>
<definitions name='EchoService' targetNamespace='http://echo/'
xmlns='http://schemas.xmlsoap.org/wsdl/'
xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'
xmlns:tns='http://echo/'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<types>
<xs:schema targetNamespace='http://echo/' version='1.0'
xmlns:tns='http://echo/'
xmlns:xs='http://www.w3.org/2001/XMLSchema'>
<xs:complexType name='Something'>
<xs:sequence>
<xs:element minOccurs='0' name='arg0' type='xs:string' />
</xs:sequence>
</xs:complexType>
<xs:complexType name='A'>
<xs:sequence>
<xs:element minOccurs='0' name='arg0' type='xs:string' />
</xs:sequence>
</xs:complexType>
<xs:complexType name='B'>
<xs:complexContent>
<xs:extension base="tns:A">
<xs:sequence>
<xs:element minOccurs='0' name='arg1' type='xs:string' />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name='C'>
<xs:complexContent>
<xs:extension base="tns:B">
<xs:sequence>
<xs:element minOccurs='0' name='arg2' type='xs:string' />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="BResponse">
<xs:sequence>
<xs:element name="something" type="tns:Something" minOccurs="1" maxOccurs="1" nillable="true"/>
<xs:element name="b" type="tns:B" minOccurs="1" maxOccurs="1" nillable="true"/>
</xs:sequence>
</xs:complexType>
<xs:element name="bResponse" type="tns:BResponse"/>
<xs:element name="something" type="tns:Something"/>
</xs:schema>
</types>
<message name='GetB_Request' />
<message name='GetB_GetBResponse'>
<part name='para' element="tns:bResponse"/>
</message>
<portType name='GetB'>
<operation name='getB' >
<input message='tns:GetB_Request'/>
<output message='tns:GetB_GetBResponse' />
</operation>
</portType>
<binding name='GetBBinding' type='tns:GetB'>
<soap:binding style='document' transport='http://schemas.xmlsoap.org/soap/http' />
<operation name='getB'>
<soap:operation soapAction='' />
<input>
<soap:body use='literal' />
</input>
<output>
<soap:body use='literal' />
</output>
</operation>
</binding>
<service name='GetBService'>
<port binding='tns:GetBBinding' name='GetBPort'>
<soap:address location='REPLACE_WITH_ACTUAL_URL' />
</port>
</service>
</definitions>
We have an A->B->C Class Hierarchy here, and a BResponse Complex Type which consists of a "B" and a "Something". Note the "minOccurs=1 maxOccurs=1 nillable=true " . If I throw the file at wsconsume it creates a number of classes. The BResponse Class looks like this:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BResponse", propOrder = {
"something",
"b"
})
public class BResponse {
@XmlElement(required = true, nillable = true)
protected Something something;
@XmlElement(required = true, nillable = true)
protected B b;
....}
I have written a very simple Server:
@javax.jws.WebService(endpointInterface="echo.GetB", serviceName="GetBService", targetNamespace="http://echo/", portName="GetBPort" )
public class DummyGetB implements GetB {
public BResponse getB() {
BResponse response = new BResponse();
C c = new C();
c.setArg0("1");
c.setArg1("2");
c.setArg2("3");
response.setB(c);
return response;
}
}
and a Client:
public class Client {
public static void main(String[] args) throws Exception {
GetBService getB = new GetBService(new URL("http://127.0.0.1:8080/server?wsdl"),new QName("http://echo/", "GetBService"));
GetB getBPort = getB.getGetBPort();
BResponse bResponse = getBPort.getB();
System.out.println(bResponse.getB().getClass());
B b = bResponse.getB();
System.out.println(b.getArg0());
System.out.println(b.getArg1());
C c = (C)bResponse.getB();
System.out.println(c.getArg2());
}
If I try this example I get:
class echo.B
1
2
Exception in thread "main" java.lang.ClassCastException: echo.B
at at.ac.arsenal.Client.main(Client.java:53)
Only a "B" gets transmitted, although it should be a "C"
Now, to get the behavior I was talking about change the minOccurrs parameter of something element of BResponse to 0:
..............
<xs:complexType name="BResponse">
<xs:sequence>
<xs:element name="something" type="tns:Something" minOccurs="0" maxOccurs="1" nillable="true"/>
<xs:element name="b" type="tns:B" minOccurs="1" maxOccurs="1" nillable="true"/>
</xs:sequence>
</xs:complexType>
................
Then rerun wsconsume. The generated BResponse class now looks like this. Notice the JAXBElement type of variable something;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BResponse", propOrder = {
"something",
"b"
})
public class BResponse {
@XmlElementRef(name = "something", type = JAXBElement.class)
protected JAXBElement<Something> something;
@XmlElement(required = true, nillable = true)
protected B b;
I Recompile and Redeploy the server then rerun the Client. The output is now:
class echo.C
1
2
3
now C gets transmitted and the arg2 property has the correct value.
As I said before this is of course no solution to the original problem, but I think it might be useful in tracking down the source of it.