Axis doesn't propertly support JavaBeans with array-type properties.
--------------------------------------------------------------------

         Key: AXIS-2202
         URL: http://issues.apache.org/jira/browse/AXIS-2202
     Project: Apache Axis
        Type: Bug
  Components: Serialization/Deserialization  
    Versions: current (nightly), 1.2, 1.2.1    
 Reporter: Andrei Iltchenko
    Priority: Critical


Axis fails to adequately support JavaBean classes with array-type properties 
when objects of such classes are deserialized by a service endpoint exposed 
with JBoss.

The problem occurs with those JavaBean array-type properties whose setters and 
getters are not idempotent -- i.e. given a property called 'Prop', an array 
value 'val1',
and a call to the the property's setter and getter:

BeanClass   bean = ...;
ValueType   val1 = ...;
bean.setProp(val1);
ValueType   val2 = bean.getProp();

val1 != val2.

In other words Axis will work fine with the following JavaBean:

public class JavaBean1 {
    Double   values[];
    Double[]  getValues() {
        return  values;
    }
    void  setValues(Double values[]) {
        this.values = values;
    }
}

but will fail to work with JavaBean2:

public class JavaBean2 {
    ArrayList   values;
    Double[]  getValues() {
        return  (Double[]) values.toArray(new Double[0]);
    }
    void  setValues(Double values[]) {
        this.values.clear();
        this.values.addAll(java.util.Arrays.asList(values);
    }
}

I investigated the cause of the problem and tracked it down to the 'set(Object, 
int, Object)' method of the 'org.apache.axis.utils.BeanPropertyDescriptor' 
class. Presented below is the code of the method with my fix for the problem 
(another problem with this method is that it makes an unnecessary call to the 
property's setter when growing the array, the fix takes care of that too). I 
will also attach a diffs file for the patch:

    public void set(Object obj, int i, Object newValue) 
        throws InvocationTargetException, IllegalAccessException {
        // Set the new value
        if (isIndexed()) {
            IndexedPropertyDescriptor id = (IndexedPropertyDescriptor)myPD;
            growArrayToSize(obj, id.getIndexedPropertyType(), i);
            id.getIndexedWriteMethod().invoke(obj,
                                              new Object[] {
                                                  new Integer(i), newValue});
        } else {
            // Not calling 'growArrayToSize' to avoid an extra call to the
            // property's setter. The setter will be called at the end anyway.
            // growArrayToSize(obj, myPD.getPropertyType().getComponentType(), 
i);
            Object array = get(obj);
            if (array == null || Array.getLength(array) <= i) {
                Class componentType = getType().getComponentType();
                Object newArray = Array.newInstance(componentType, i + 1);
                // Copy over the old elements
                if (array != null) {
                    System.arraycopy(array, 0, newArray, 0, 
Array.getLength(array));
                }
                array = newArray;
            }
            Array.set(array, i, newValue);
            // Fix for non-indempondent array-type propertirs.
            // Make sure we call the property's setter.
            set(obj, array);
        }
    }

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira

Reply via email to