You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by bu...@apache.org on 2002/09/12 15:07:01 UTC

DO NOT REPLY [Bug 12572] New: - none SOAP Array Deserialization in BeanDeserializer incl. fix

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=12572>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=12572

 none SOAP Array Deserialization in BeanDeserializer incl. fix

           Summary:  none SOAP Array Deserialization in BeanDeserializer
                    incl. fix
           Product: Axis
           Version: current (nightly)
          Platform: Other
        OS/Version: Other
            Status: NEW
          Severity: Normal
          Priority: Other
         Component: Serialization/Deserialization
        AssignedTo: axis-dev@xml.apache.org
        ReportedBy: schmitz@objectcode.de


Hi

I am calling a SOAP service which sends messages containing elements with 
multiple (as I have been told) non SOAP Arrays , which looks as follows:

<elem>
 <arr1>xxx</arr1>
 <arr2>xxx</arr2>
 <arr1>xxx</arr1>
 <arr2>xxx</arr2>
 <arr1>xxx</arr1>
 <arr2>xxx</arr2>
 <arr1>xxx</arr1>
 <arr2>xxx</arr2>
</elem>

The BeanDeserializer in the current implementation assumes, that multiple non 
SOAP arrays elements appear sequentially as in: 
<elem>
 <arr1>xxx</arr1>
 <arr1>xxx</arr1>
 <arr1>xxx</arr1>
 <arr1>xxx</arr1>
 <arr2>xxx</arr2>
 <arr2>xxx</arr2>
 <arr2>xxx</arr2>
 <arr2>xxx</arr2>
</elem>
This is expressed in the fact, that the IndexCounter inside the 
org.apache.axis.encoding.ser.BeanDeserializer is reset to -1 each time a childs 
qname is different from the previous childs qname. In the first case stated 
above only one array element is filled instead of four for each array, 
containing the last value in the list.

I do not have very good knowledge about the SOAP protocol, but a friend of mine 
told me, that both ways should be XML conform.

So I would like to offer a fix for this problem.

Instead of using the prevQName (which can be removed) I use a Hashtable to 
store the array indizes for each child Array. The Hash is initialized in the 
onStartElement method.
It now looks like : 
....
    public void onStartElement(String namespace, String localName,
                               String prefix, Attributes attributes,
                               DeserializationContext context)
            throws SAXException {

        // Reset Array Indexes
        collectionIndexHash = new Hashtable() ;
....

Further I removed the handling of the prevQName Attribute 
        // The collectionIndex needs to be reset for Beans with multiple arrays
/*        if ((prevQName == null) || (!prevQName.equals(elemQName))) {
            collectionIndex = -1;
        }
        prevQName = elemQName;
*/

finally I changed the onStartChild method. This may not be the most efficient 
Method, but it works.
....
        // Register value target
        if (propDesc.isWriteable()) {
            // If this is an indexed property, and the deserializer we found
            // was NOT the ArrayDeserializer, this is a non-SOAP array:
            // <bean>
            //   <field>value1</field>
            //   <field>value2</field>
            // ...
            // In this case, we want to use the collectionIndex and make sure
            // the deserialized value for the child element goes into the
            // right place in the collection.
            if (propDesc.isIndexed() && !(dSer instanceof ArrayDeserializer)) {
                Integer indexHolder = (Integer) collectionIndexHash.get
(localName);
                if ( indexHolder == null ) {
                    collectionIndex = 0 ;
                }else{
                    collectionIndex = indexHolder.intValue()+1;
                }
                collectionIndexHash.put(localName , new Integer
(collectionIndex));
                    dSer.registerValueTarget(new BeanPropertyTarget(value,
                                                    propDesc, collectionIndex));
            } else {
                // If we're here, the element maps to a single field value,
                // whether that be a "basic" type or an array, so use the
                // normal (non-indexed) BeanPropertyTarget form.
                collectionIndex = -1;
                dSer.registerValueTarget(new BeanPropertyTarget(value,
                                                                propDesc));
            }
        }
....

Here is a diff against Version 1.51


cvs -z9 diff -w BeanDeserializer.java (in directory C:\apache\xml-
axis.head\java\src\org\apache\axis\encoding\ser\)
Index: BeanDeserializer.java
===================================================================
RCS file: /home/cvspublic/xml-
axis/java/src/org/apache/axis/encoding/ser/BeanDeserializer.java,v
retrieving revision 1.51
diff -w -r1.51 BeanDeserializer.java
79a80,81
> import java.util.Hashtable;
> 
96c98
<     protected QName prevQName;
---
> //    protected QName prevQName;
103a106,107
>     protected Hashtable collectionIndexHash = null ;
> 
161a166
> 
198c203
<         if ((prevQName == null) || (!prevQName.equals(elemQName))) {
---
> /*        if ((prevQName == null) || (!prevQName.equals(elemQName))) {
202c207
< 
---
> */
282c287,293
<                     collectionIndex++;
---
>                 Integer indexHolder = (Integer) collectionIndexHash.get
(localName);
>                 if ( indexHolder == null ) {
>                     collectionIndex = 0 ;
>                 }else{
>                     collectionIndex = indexHolder.intValue()+1;
>                 }
>                 collectionIndexHash.put(localName , new Integer
(collectionIndex));
328a340,342
>         // Reset Array Indexes
>         collectionIndexHash = new Hashtable() ;
> 
335a350
> 

I would like to see something like this implemented in 1.0 (because I need it 
to call the service :-).

regards

  Oliver Schmitz