Polymorphism in SOAP calls – Flex calling a Java Web service
In the current application I am working on, we are using a Flex client that communicates with a Web service on the server side. The client's VOs are automatically generated.
One of the things that bothered me in that model is – how can I implement polymorphysm in this model?
Let's assume that in the wsdl there is a complex type A.
Two types extend it (using xsd:extension) – B1 and B2.
Another type C has element “a” of type A.
Now, this means that SOAP messages with element of type C can have in their property “a” elements of types A, B1 and B2. Without special treatment, the receiving side (either the server on a SOAP request or the client on a SOAP response) will understand the object as type A, and won't generate the correct object.
There are two ways to solve this that I know of.
1. Substitution Group
See also here.
The name of the element is changed according to the actual element. Meaning that if we are using B1, the element's name will be “b1” and not “a”.
So instead of :
The SOAP will contain:
To do that, the types B1 and B2 needs to have element defined with attribute substitutionGroup.
So now everywhere element “a” is used it can be substituted by element b1 or b2.
It's a good solution – the problem is that Flex doesn't support substitutionGroup. It can be implemented, though, by overriding the SOAPDecoder and SOAPEncoder.
See also here.
The elements in the SOAP request will include an additional xsi:type attribute. This attribute tells the receiving end what is the actual type of that element. This attribute can be applied only to the inheriting elements.
I've chosen to implement this solution because it seemed easier working on the Flex's side. I would love to hear if there are any ideas how to implement the other solution.
For this to work, we need both the Java side and the Flex side to understand xsi:type attributes (i.e. - to read and write these attributes).
The server I have uses Apache Cxf to generate the proxy classes. The solution was found here.
Besides adding this globalBindings element, you'll need to run the xjc with -extension argument.
Since I've been using wsdl2java in ant, I added it as the parameter -xjc-extension like this:
<java classname="org.apache.cxf.tools.wsdlto.WSDLToJava" fork="true">
The solution was found here. The link points to the only section relevant to this issue. You'll need to override the SOAPEncoder and SOAPDecoder of the web service, and add their CxfSchemaTypeRegistryProxy class.
Pay attention to the comments section – there are some important updates to the decoder (and an update I posted to the CxfSchemaTypeRegistryProxy class).