I looked at the sample you provided, and I I've solved your issue (though a bit too late, so it seems
). It has to do with the difference between elements and types in XSD. A type (complex of simple) in an XSD schema is "abstract", meaning that it cannot be used directly, but only referred to in elements or attributes. Though not entirely the same, you can compare a XSD type to an interface in Java, and it's even more like a typedef in C.
When you generate Java code from the XSD using JAXB, it also generates a class for the type. In the sample you sent me, this was part of the XSD:
Code:
<element name="TestRq" type="tns:TestRqTyp" />
<complexType name="TestRqTyp" mixed="false">
<sequence>
<element name="TestInput" type="string" minOccurs="0" />
</sequence>
</complexType>
<element name="TestRs" type="tns:TestRsTyp" />
<complexType name="TestRsTyp" mixed="false">
<sequence>
<element name="TestOutput" type="string" />
</sequence>
</complexType>
This resulted in four generated interfaces: TestRq and TestRs (for the elements), TestRqTyp and TestRsTyp (for the complexTypes). The element interfaces extend the type interfaces, but they are not the same! One is the element, the other is the type.
Now, the endpoint code contained the following (I've removed some debugging code):
Code:
public Object invokeInternal(Object requestObject) throws Exception {
TestRqTyp request = (TestRqTyp) requestObject;
TestService ts = new TestService();
TestRsTyp response = ts.getRs(request);
return response;
}
Note that you're using the type interfaces here, and not the elements. This is ok for the requestObject, because the element extends the type. But this is not OK for the response object, because that results in the type being written, without a wrapping TestRs element:
Code:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<TestOutput xmlns="http://www.mycompany.com">BenTestOutputValue</TestOutput>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
To fix this, I changed the above code to:
Code:
public Object invokeInternal(Object requestObject) throws Exception {
TestRq request = (TestRq) requestObject;
TestService ts = new TestService();
TestRs response = ts.getRs(request);
return response;
}
which results in the following response message:
Code:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<TestRs xmlns="http://www.mycompany.com">
<TestOutput>BenTestOutputValue</TestOutput>
</TestRs>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
So, in conclusion, you have to cast the requestObject to a generated element when using JAXB 1.0. When using JAXB 2.0, this is a different matter, because it does not generate classes for elements. So then you have to cast it to a JAXBElement, like you've shown in your post. This is rather unfortunate, because it ties your endpoint code to the marshalling technology you use, while the whole point of the Spring OXM abstractions is to forego this tie-in. I don't know if there is any way to work around this unnecessary tie-in.