Uploaded image for project: 'Axis2-C'
  1. Axis2-C
  2. AXIS2C-1071

WSDL2C, ADB & xsi:type based deserialization

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • None
    • 1.7.0
    • core/addressing
    • None

    Description

      I have the problem of having to work with a wsdl interface the makes use of type extensions and xsi:type. For example:

      <complexType name="VirtualHardware">
      <complexContent>
      <extension base="vim25:DynamicData">
      <sequence>
      <element name="numCPU" type="xsd:int" />
      <element name="memoryMB" type="xsd:int" />
      <element name="device" type="vim25:VirtualDevice" minOccurs="0" maxOccurs="unbounded" />
      </sequence>
      </extension>
      </complexContent>
      </complexType>

      where the VirtualDevice type is extended in various ways to reflect different kind of device types:

      <complexType name="VirtualController">
      <complexContent>
      <extension base="vim25:VirtualDevice">
      <sequence>
      <element name="busNumber" type="xsd:int" />
      <element name="device" type="xsd:int" minOccurs="0" maxOccurs="unbounded" />
      </sequence>
      </extension>
      </complexContent>
      </complexType>

      The issue I am running into is that WSDL2C does not seem to support this kind of xsi:type based type serialization/deserialization (which admittedly fits really poorly with a non-object oriented language like C). You could probably make it work by storing type information in the generated structs, combined with a type registry.

      Any suggestions on workarounds other than using the XML model?

      Attachments

        1. polymorphism.patch
          40 kB
          SĂ©rgio Gomes
        2. polymorphic.zip
          74 kB
          Dimuthu Gamage

        Activity

          dimuthu Dimuthu Gamage added a comment -

          Fixed.

          dimuthu Dimuthu Gamage added a comment - Fixed.

          Ah, I missed those, good catch. Thanks for committing, I'm glad the patch was useful

          sgomes SĂ©rgio Gomes added a comment - Ah, I missed those, good catch. Thanks for committing, I'm glad the patch was useful
          dimuthu Dimuthu Gamage added a comment -

          Commited the patch provided by Sergio(from revision 801306).

          It is a really great patch. I wrote a simple test case (attached) and polymorphic types are working as expected

          I had to do few changes though like,
          1. adding "xsi:type" attribute at the serialization
          2. there were variables declared in the middle of the blocks. That is not compiled in Visual Studio compilers.

          dimuthu Dimuthu Gamage added a comment - Commited the patch provided by Sergio(from revision 801306). It is a really great patch. I wrote a simple test case (attached) and polymorphic types are working as expected I had to do few changes though like, 1. adding "xsi:type" attribute at the serialization 2. there were variables declared in the middle of the blocks. That is not compiled in Visual Studio compilers.

          I've got an initial implementation of a fix to this problem, submitting it below.

          Here are some notes.

          PROBLEM: In Axis2/C, ADB objects are stripped down to their abstract types when being sent or received in SOAP requests.
          SOLUTION: To implement an "extension handler" that is aware of all types, and can pick between them. This is done by:
          a) Storing an object's type in the object itself and using that knowledge when serializing (converting to XML) and "free"ing.
          b) Reading the xsi:type in incoming XML, and using that to invoke the specific deserialization function (XML to object).

          Implementation details:

          The code I implemented patches the ADB code generator to generate two new files, axis2_extension_mapper.h/c, that are aware of all extensions and can pick the right type and method to serialize / deserialize. This is done with a different model in the same XSL files.

          I added property_Type, so that each struct is aware of its type. This is the correct way of checking which type an object should be cast to, after deserializing (the property is filled by the deserialization method, upon creation of the specific object).

          As for changing the serialization / deserialization, I decided to rename the methods in all the objects to *_serialize_obj and *_deserialize_obj, and to keep *_serialize and *_deserialize as wrappers, that call the serialize and deserialize methods in the extension handler module. This module then picks the correct *_serialize_obj or *_deserialize_obj method. These changes were done to minimize number of lines of code changed. 'free' has also been "polymorphed", and "create" is updated to fill in property_Type.

          This has been tested on requests and responses, client-side (I haven't really had the chance to test the patch server-side).

          Please let me know if you have any comments or suggestions!

          sgomes SĂ©rgio Gomes added a comment - I've got an initial implementation of a fix to this problem, submitting it below. Here are some notes. PROBLEM: In Axis2/C, ADB objects are stripped down to their abstract types when being sent or received in SOAP requests. SOLUTION: To implement an "extension handler" that is aware of all types, and can pick between them. This is done by: a) Storing an object's type in the object itself and using that knowledge when serializing (converting to XML) and "free"ing. b) Reading the xsi:type in incoming XML, and using that to invoke the specific deserialization function (XML to object). Implementation details: The code I implemented patches the ADB code generator to generate two new files, axis2_extension_mapper.h/c, that are aware of all extensions and can pick the right type and method to serialize / deserialize. This is done with a different model in the same XSL files. I added property_Type, so that each struct is aware of its type. This is the correct way of checking which type an object should be cast to, after deserializing (the property is filled by the deserialization method, upon creation of the specific object). As for changing the serialization / deserialization, I decided to rename the methods in all the objects to *_serialize_obj and *_deserialize_obj, and to keep *_serialize and *_deserialize as wrappers, that call the serialize and deserialize methods in the extension handler module. This module then picks the correct *_serialize_obj or *_deserialize_obj method. These changes were done to minimize number of lines of code changed. 'free' has also been "polymorphed", and "create" is updated to fill in property_Type. This has been tested on requests and responses, client-side (I haven't really had the chance to test the patch server-side). Please let me know if you have any comments or suggestions!
          aaron.oneal Incarnadine added a comment -

          I'm seeing the same problem. WSDL that makes use of <extension base="..."/> (derived types) doesn't work with Axis2/C.

          aaron.oneal Incarnadine added a comment - I'm seeing the same problem. WSDL that makes use of <extension base="..."/> (derived types) doesn't work with Axis2/C.
          smeder Sam Meder added a comment -

          Sure, lets using the snippets of schema in my original report the following xml is causing problems:

          <VirtualHardware>
          ...
          <device xsi:type="vim25:VirtualController>
          ...
          </device>
          </VirtualHardware>

          Note that device was declared as being of type vim25:VirtualDevice, the base type for vim25:VirtualController. To put it in object oriented terms: VirtualHardware declares a member using the VirtualDevice base class type. At runtime it is initialized with a instance of a sub class (Virtual Controller). The issue is that Axis2c will only resolve the base class.

          From what I could tell from the generated adb stubs (adb for the sub types is never generated by the way, but I guess there may be a command line switch for that) you could do something like the following to support this:

          • The generated structs must have a type member as their first member
          • The generated structs must be registered with a type registry that maps their type to a function pointers for serialization/desirialization and possibly information that allows one to check the type hierarchy
          • The generated serialization/deserialization code needs to be changed to make use of this registry
          smeder Sam Meder added a comment - Sure, lets using the snippets of schema in my original report the following xml is causing problems: <VirtualHardware> ... <device xsi:type="vim25:VirtualController> ... </device> </VirtualHardware> Note that device was declared as being of type vim25:VirtualDevice, the base type for vim25:VirtualController. To put it in object oriented terms: VirtualHardware declares a member using the VirtualDevice base class type. At runtime it is initialized with a instance of a sub class (Virtual Controller). The issue is that Axis2c will only resolve the base class. From what I could tell from the generated adb stubs (adb for the sub types is never generated by the way, but I guess there may be a command line switch for that) you could do something like the following to support this: The generated structs must have a type member as their first member The generated structs must be registered with a type registry that maps their type to a function pointers for serialization/desirialization and possibly information that allows one to check the type hierarchy The generated serialization/deserialization code needs to be changed to make use of this registry
          dimuthu Dimuthu Gamage added a comment -

          Hi Sam,

          Is that meaning to serialize the elements with the type information, for an example to like this,

          <numCPU xsi:type="xsd:int">5<numCPU/>

          Anyway adb stores type information in the structs, (i.e. all the attribute is in the mapped c type from the xsd type). Can you explain your issue a little bit more?

          dimuthu Dimuthu Gamage added a comment - Hi Sam, Is that meaning to serialize the elements with the type information, for an example to like this, <numCPU xsi:type="xsd:int">5<numCPU/> Anyway adb stores type information in the structs, (i.e. all the attribute is in the mapped c type from the xsd type). Can you explain your issue a little bit more?

          People

            dimuthu Dimuthu Gamage
            smeder Sam Meder
            Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: