Axis
  1. Axis
  2. AXIS-2250

AXIS array serialization: Incorrect element names of items in a list

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Critical Critical
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Labels:
    • Environment:
      plattform: i386, OS: WinXP Pro, Java: 1.4.2_06

      Description

      -Web Service deployed as "wrapped/literal"

      The web service returns a custom bean style class which has an array of another custom bean style class as a member.

      In the WSDL-file the array of the custom type is being described correctly:

      <complexType name="ArrayOf_tns1_EntityTypeBean">
      <sequence>
      <element maxOccurs="unbounded" minOccurs="0" name="item" type="tns1:EntityTypeBean"/>
      </sequence>
      </complexType>

      But when the Java object is being serialized during runtime the array is being transfered to a list whose member elements DO NOT have the name "item" as expected from the WSDL-file. All members of the list have the same name as the list itself:

      <entities>
      <entities>
      ...
      </entities>
      <entities>
      ...
      </entities>
      <entities>
      ...
      </entities>
      </entities>

      But this is expected:

      <entities>
      <item>
      ...
      </item>
      <item>
      ...
      </item>
      <item>
      ...
      </item>
      </entities>

      1. Post.zip
        19 kB
        Karthik R
      2. beans.zip
        3 kB
        Denis Schlesinger

        Activity

        Hide
        Ragulan added a comment - - edited

        We have fixed this issue by the following fix:

        Modifed the code to get the childNodeName of the NodeList from the server-config.wsdd as follows:

        My Sample Code:

        server-config.wsdd:
        <typeMapping
        xmlns:ns="java:service"
        qname="ns:subPackage" // decides the childNode name of the NodeList
        type="java:service.Package"
        serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
        deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
        encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
        />

        <arrayMapping
        xmlns:ns="java:service"
        qname="ns:packages"
        type="java:service.Package[]"
        serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
        deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
        encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
        />

        Wsdl:
        <wsdl:types>
        <schema targetNamespace="java:service" xmlns="http://www.w3.org/2001/XMLSchema">
        <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
        <complexType name="service">
        <sequence>
        //element name is the parentNode's Name of the NodeList (this name is from java class) and type is from wsdd file
        <element name="packages" nillable="true" type="tns1:packages"/>
        </sequence>
        </complexType>
        <complexType name="packages">
        <complexContent>
        <restriction base="soapenc:Array">
        //arrayType is from wsdd file
        <attribute ref="soapenc:arrayType" wsdl:arrayType="tns1:subPackage[]"/>
        </restriction>
        </complexContent>
        </complexType>
        <complexType name="subPackage"> // element name is the childNode's Name in the NodeList (this name is from wsdd file)
        <sequence>
        // element name is the inner node of the childNode (this name is from java class)
        <element name="packageName" nillable="true" type="soapenc:string"/>
        </sequence>
        </complexType>
        </schema>
        </wsdl:types>

        Response:
        <firstMethodReturn xmlns:ns2="java:service" xsi:type="ns2:service">
        <packages xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:Array" soapenc:arrayType="ns2:subPackage[2]">
        <subPackage xsi:type="ns2:subPackage">
        <packageName xsi:type="soapenc:string">First</packageName>
        </subPackage>
        <subPackage xsi:type="ns2:subPackage">
        <packageName xsi:type="soapenc:string">Second</packageName>
        </subPackage>
        </packages>
        </firstMethodReturn>

        Changes Needs to be done:
        1) Change the qname in the typeMapping of the childNode of the NodeList. This qname is used as the childNode's Name in the NodeList.
        for e.g:
        In the above sample .wsdd file, i ve changed the qname in the typeMapping as qname="ns:subPackage".
        So, the childNode's Name in the NodeList will be "subPackage".

        2) In org.apache.axis.encoding.ser.ArraySerializer Class, include the below code marked in blue.

        if (!maxOccursUsage)

        { serializeAttr = null; // since we are putting them here context.startElement(name, attributes); if (itemQName != null) elementName = itemQName; else if(componentQName != null) elementName = componentQName; else elementName = new QName(name.getNamespaceURI(), componentTypeQName.getLocalPart()); }

        Let us know if somebody have a problem with this solution.

        This Fix is done by Team in VERIZON . Special Thanks to Chandrababu who made this break

        Show
        Ragulan added a comment - - edited We have fixed this issue by the following fix: Modifed the code to get the childNodeName of the NodeList from the server-config.wsdd as follows: My Sample Code: server-config.wsdd: <typeMapping xmlns:ns="java:service" qname="ns:subPackage" // decides the childNode name of the NodeList type="java:service.Package" serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> <arrayMapping xmlns:ns="java:service" qname="ns:packages" type="java:service.Package[]" serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> Wsdl: <wsdl:types> <schema targetNamespace="java:service" xmlns="http://www.w3.org/2001/XMLSchema"> <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/> <complexType name="service"> <sequence> //element name is the parentNode's Name of the NodeList (this name is from java class) and type is from wsdd file <element name="packages" nillable="true" type="tns1:packages"/> </sequence> </complexType> <complexType name="packages"> <complexContent> <restriction base="soapenc:Array"> //arrayType is from wsdd file <attribute ref="soapenc:arrayType" wsdl:arrayType="tns1:subPackage[]"/> </restriction> </complexContent> </complexType> <complexType name="subPackage"> // element name is the childNode's Name in the NodeList (this name is from wsdd file) <sequence> // element name is the inner node of the childNode (this name is from java class) <element name="packageName" nillable="true" type="soapenc:string"/> </sequence> </complexType> </schema> </wsdl:types> Response: <firstMethodReturn xmlns:ns2="java:service" xsi:type="ns2:service"> <packages xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:Array" soapenc:arrayType="ns2:subPackage [2] "> <subPackage xsi:type="ns2:subPackage"> <packageName xsi:type="soapenc:string">First</packageName> </subPackage> <subPackage xsi:type="ns2:subPackage"> <packageName xsi:type="soapenc:string">Second</packageName> </subPackage> </packages> </firstMethodReturn> Changes Needs to be done: 1) Change the qname in the typeMapping of the childNode of the NodeList. This qname is used as the childNode's Name in the NodeList. for e.g: In the above sample .wsdd file, i ve changed the qname in the typeMapping as qname="ns:subPackage". So, the childNode's Name in the NodeList will be "subPackage". 2) In org.apache.axis.encoding.ser.ArraySerializer Class, include the below code marked in blue. if (!maxOccursUsage) { serializeAttr = null; // since we are putting them here context.startElement(name, attributes); if (itemQName != null) elementName = itemQName; else if(componentQName != null) elementName = componentQName; else elementName = new QName(name.getNamespaceURI(), componentTypeQName.getLocalPart()); } Let us know if somebody have a problem with this solution. This Fix is done by Team in VERIZON . Special Thanks to Chandrababu who made this break
        Hide
        Ragulan added a comment -

        Can somebody given an update on this issue.

        We are facing this issue now

        Show
        Ragulan added a comment - Can somebody given an update on this issue. We are facing this issue now
        Hide
        Karthik R added a comment -

        1.Wsdl
        2. src generated wsdl2java
        3. server-config.wsdd, just generated by giving -server option

        Show
        Karthik R added a comment - 1.Wsdl 2. src generated wsdl2java 3. server-config.wsdd, just generated by giving -server option
        Hide
        Karthik R added a comment -

        Hello Narayan,

        Changing WSDD is possible only if you expose the service rite. In our Case, we are consuming from .Net.

        How to Solve in that case?

        Scenario is simple and similar to my previous user

        <soapenv:Body>
        <ns1:getEmployeeDetails soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://service.three.com">
        <listOfEmps soapenc:arrayType="ns1:Employee[5]" xsi:type="soapenc:Array" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
        <listOfEmps href="#id0"/> <!-- Note here item tag is not coming -->
        <listOfEmps href="#id1"/>
        <listOfEmps href="#id2"/>
        </listOfEmps>
        </ns1:getEmployeeDetails>
        <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:Employee" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="http://service.three.com">
        <empName xsi:type="soapenc:string">
        Ganesh
        </empName>
        <empNo xsi:type="soapenc:string">
        1111
        </empNo>
        <salary xsi:type="soapenc:string">
        30000
        </salary>
        </multiRef>

        <multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns4:Employee" xmlns:ns4="http://service.three.com" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
        <empName xsi:type="soapenc:string">
        Ranesh
        </empName>
        <empNo xsi:type="soapenc:string">
        2111
        </empNo>
        <salary xsi:type="soapenc:string">
        30000
        </salary>
        </multiRef>

        <multiRef id="id2" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns5:Employee" xmlns:ns5="http://service.three.com" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
        <empName xsi:type="soapenc:string">Karthik</empName>
        <empNo xsi:type="soapenc:string">3111</empNo>
        <salary xsi:type="soapenc:string">30000</salary>
        </multiRef>

        </soapenv:Body>
        </soapenv:Envelope>

        Can anyone please advise on this of client?

        Show
        Karthik R added a comment - Hello Narayan, Changing WSDD is possible only if you expose the service rite. In our Case, we are consuming from .Net. How to Solve in that case? Scenario is simple and similar to my previous user <soapenv:Body> <ns1:getEmployeeDetails soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://service.three.com"> <listOfEmps soapenc:arrayType="ns1:Employee [5] " xsi:type="soapenc:Array" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> <listOfEmps href="#id0"/> <!-- Note here item tag is not coming --> <listOfEmps href="#id1"/> <listOfEmps href="#id2"/> </listOfEmps> </ns1:getEmployeeDetails> <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:Employee" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="http://service.three.com"> <empName xsi:type="soapenc:string"> Ganesh </empName> <empNo xsi:type="soapenc:string"> 1111 </empNo> <salary xsi:type="soapenc:string"> 30000 </salary> </multiRef> <multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns4:Employee" xmlns:ns4="http://service.three.com" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> <empName xsi:type="soapenc:string"> Ranesh </empName> <empNo xsi:type="soapenc:string"> 2111 </empNo> <salary xsi:type="soapenc:string"> 30000 </salary> </multiRef> <multiRef id="id2" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns5:Employee" xmlns:ns5="http://service.three.com" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> <empName xsi:type="soapenc:string">Karthik</empName> <empNo xsi:type="soapenc:string">3111</empNo> <salary xsi:type="soapenc:string">30000</salary> </multiRef> </soapenv:Body> </soapenv:Envelope> Can anyone please advise on this of client?
        Hide
        Narayan Singh Dhillon added a comment -

        Got the temp fix.. change the generated WSDD file to include new attribute returnItemQName="item" inside your operation name.

        Show
        Narayan Singh Dhillon added a comment - Got the temp fix.. change the generated WSDD file to include new attribute returnItemQName="item" inside your operation name.
        Hide
        Narayan Singh Dhillon added a comment -

        I am having the same issue where XML produced contains array elements with same name as list. I am using axis1.4, Do you have any work around to the above problem?

        Snippet -
        <xs:complexType name="ArrayOfOutputList">
        <xs:complexContent>
        <xs:restriction base="soapenc:Array">
        <xs:sequence>
        <xs:element maxOccurs="unbounded" name="item" type="custom-types:Output"/>
        </xs:sequence>

        </xs:restriction>
        </xs:complexContent>
        </xs:complexType>

        <xs:complexType name="Output">
        <xs:sequence>
        <xs:element name="OutputDataID" type="xs:unsignedLong"/>
        <xs:element name="DataType" type="xs:string" minOccurs="0"/>
        </xs:sequence>
        </xs:complexType>

        generated XML from Axis -

        <Output>
        <Output><OutputDataID>1</OutputDataID><DataType>TEST</DataType></Output>
        <Output><OutputDataID>2</OutputDataID><DataType>TEST</DataType></Output>
        </Output>

        Show
        Narayan Singh Dhillon added a comment - I am having the same issue where XML produced contains array elements with same name as list. I am using axis1.4, Do you have any work around to the above problem? Snippet - <xs:complexType name="ArrayOfOutputList"> <xs:complexContent> <xs:restriction base="soapenc:Array"> <xs:sequence> <xs:element maxOccurs="unbounded" name="item" type="custom-types:Output"/> </xs:sequence> </xs:restriction> </xs:complexContent> </xs:complexType> <xs:complexType name="Output"> <xs:sequence> <xs:element name="OutputDataID" type="xs:unsignedLong"/> <xs:element name="DataType" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType> generated XML from Axis - <Output> <Output><OutputDataID>1</OutputDataID><DataType>TEST</DataType></Output> <Output><OutputDataID>2</OutputDataID><DataType>TEST</DataType></Output> </Output>
        Hide
        René Zanner added a comment -

        It seems this bug exists also in version 1.3, so please change the "Affects version" field to "1.3"!

        We use Axis 1.3 with a hand written WSDD as well as a manually modified WSDL. Our Axis client stubs are generated using this manually modified WSDL file. The stubs expect an "item" element inside the Array wrapper element but deserialize the wrong response without an error. How does that work???

        So the Axis client stubs (using the ArrayDeserializer) ignore the wrong response from the server and simply deserialize despite the wrong xml structure.

        Maybe that's the reason why nobody stumbled over it any more? Since we have a .NET client at the other side, we found this bug very quickly and need a fix as soon as possible!

        Thanks a lot!

        Show
        René Zanner added a comment - It seems this bug exists also in version 1.3, so please change the "Affects version" field to "1.3"! We use Axis 1.3 with a hand written WSDD as well as a manually modified WSDL. Our Axis client stubs are generated using this manually modified WSDL file. The stubs expect an "item" element inside the Array wrapper element but deserialize the wrong response without an error. How does that work??? So the Axis client stubs (using the ArrayDeserializer) ignore the wrong response from the server and simply deserialize despite the wrong xml structure. Maybe that's the reason why nobody stumbled over it any more? Since we have a .NET client at the other side, we found this bug very quickly and need a fix as soon as possible! Thanks a lot!
        Hide
        Chad Wilson added a comment -

        I believe this is a dupe of AXIS-2095, as it was resolved by Anil's fix mentioned there, at least in the Document/Wrapped encoding.

        Show
        Chad Wilson added a comment - I believe this is a dupe of AXIS-2095 , as it was resolved by Anil's fix mentioned there, at least in the Document/Wrapped encoding.
        Hide
        Denis Schlesinger added a comment -

        I solved it to my own needs by adding an "else" branch at org.apache.axis.encoding.ser.ArraySerializer, line 404:

        [...] else
        elementName = new QName(elementName.getNamespaceURI(), "item"); [...]

        Making the whole if-block:

        if (!maxOccursUsage)

        { serializeAttr = null; // since we are putting them here context.startElement(name, attributes); if (itemQName != null) elementName = itemQName; else if(componentQName != null) elementName = componentQName; else elementName = new QName(elementName.getNamespaceURI(), "item"); }

        Anyway, this needs to be checked by some other people as well...

        Show
        Denis Schlesinger added a comment - I solved it to my own needs by adding an "else" branch at org.apache.axis.encoding.ser.ArraySerializer, line 404: [...] else elementName = new QName(elementName.getNamespaceURI(), "item"); [...] Making the whole if-block: if (!maxOccursUsage) { serializeAttr = null; // since we are putting them here context.startElement(name, attributes); if (itemQName != null) elementName = itemQName; else if(componentQName != null) elementName = componentQName; else elementName = new QName(elementName.getNamespaceURI(), "item"); } Anyway, this needs to be checked by some other people as well...
        Hide
        Denis Schlesinger added a comment -

        An object of the class "EntityListResultBean" is being returned by the web service. The entries of the list generated from the member array "value" of type "EntityBean" have the same name as the list itself - "value". It should be "item" for each list entry. The same problem occures for all other arrays of custom types.

        Show
        Denis Schlesinger added a comment - An object of the class "EntityListResultBean" is being returned by the web service. The entries of the list generated from the member array "value" of type "EntityBean" have the same name as the list itself - "value". It should be "item" for each list entry. The same problem occures for all other arrays of custom types.

          People

          • Assignee:
            Unassigned
            Reporter:
            Denis Schlesinger
          • Votes:
            10 Vote for this issue
            Watchers:
            9 Start watching this issue

            Dates

            • Created:
              Updated:

              Development