[ 
https://issues.apache.org/jira/browse/TUSCANY-1833?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12535931
 ] 

Jiang Chen commented on TUSCANY-1833:
-------------------------------------

Thanks. That was the problem.

I assumed arrays are wrapped in a parent component. Below is the XML I used:

    <property element="ns0:personElement" many="false" name="person" 
noDefault="false">
        <ns0:null>
            <ns0:firstname/>
            <ns0:middlename/>
            <ns0:lastname/>
            <ns0:hobbies>
                <ns0:hobby>
                    <ns0:name>asdf</ns0:name>
                </ns0:hobby>
                <ns0:hobby>
                    <ns0:name>asdf</ns0:name>
                </ns0:hobby>
            </ns0:hobbies>
        </ns0:null>
    </property>

Representing arrays as a sequence of elements without a parent element 
certainly works. A bit of a catch is that I can't name the Java bean property 
"hobbies" but rather "hobby" to match with the XML element name, while the 
property is a plural.

> XML2JavaBeanTransformer has problem transforming to beans with array fields
> ---------------------------------------------------------------------------
>
>                 Key: TUSCANY-1833
>                 URL: https://issues.apache.org/jira/browse/TUSCANY-1833
>             Project: Tuscany
>          Issue Type: Bug
>          Components: Java SCA Data Binding Runtime
>    Affects Versions: Java-SCA-1.0
>            Reporter: Jiang Chen
>             Fix For: Java-SCA-Next
>
>
> I tried to use complex properties in a POJO which requires the SCA runtime at 
> injection time to convert complex XML property values into Java beans. The 
> XML2JavaBeanTransformer in the java beans data binding package seems to have 
> problem converting to beans with array members. Mapping exception was thrown.
> In both the setFieldValue and the setFieldValueUsingSetter methods of 
> org.apache.tuscany.sca.databinding.javabeans.XML2JavaBeanTransformer, when 
> the field type is Array, it probably should convert all the child elements of 
> the field value to Java objects and add them to the field value array. The 
> current implementation tries to convert the field value itself (the parent of 
> the array elements) yet using the component type of the array.
> The following fix seems to have fixed my problem.
>     private void setFieldValue(Object javaInstance,
>                                Field javaField,
>                                T fieldValue,
>                                Map<Field, List<Object>> arrayFields,
>                                TransformationContext context) throws 
> IllegalAccessException {
>         Class<?> javaFieldType = (Class<?>) javaField.getType();
>         if (javaFieldType.isArray()) {
>             Class<?> componentType = javaFieldType.getComponentType();
>             List<Object> fldValueArray = arrayFields.get(javaField);
>             if (fldValueArray == null) {
>                 fldValueArray = new ArrayList<Object>();
>                 arrayFields.put(javaField, fldValueArray);
>             }
>             
>             /*********************** Fix Starts *************************/
>             // Old code commented out:
>             // fldValueArray.add(createJavaObject(fieldValue, componentType, 
> context));
>             
>             // New code added:
>             List<T> childElements = getChildElements(fieldValue);
>             
>             for (int i = 0; i < childElements.size(); i++)
>              if (!isTextElement(childElements.get(i))) 
> fldValueArray.add(createJavaObject(childElements.get(i), componentType, 
> context));
>             /*********************** Fix Ends *************************/
>         } else {
>             javaField.setAccessible(true);
>             javaField.set(javaInstance, createJavaObject(fieldValue, 
> javaFieldType, context));
>         }
>     }
>     private void setFieldValueUsingSetter(Class javaType,
>                                           Object javaInstance,
>                                           String fieldName,
>                                           T fieldValue,
>                                           Map<Method, List<Object>> 
> arraySetters,
>                                           TransformationContext context) 
> throws IllegalAccessException,
>                                                                         
> InvocationTargetException {
>         char firstChar = Character.toUpperCase(fieldName.charAt(0));
>         StringBuilder methodName = new StringBuilder(SET + fieldName);
>         methodName.setCharAt(SET.length(), firstChar);
>         boolean methodNotFound = true;
>         for (int methodCount = 0; methodNotFound && methodCount < 
> javaType.getMethods().length; ++methodCount) {
>             Method aMethod = javaType.getMethods()[methodCount];
>             if (aMethod.getName().equals(methodName.toString())
>                     && aMethod.getParameterTypes().length == 1) {
>                 Class<?> paramType = aMethod.getParameterTypes()[0];
>                 if (paramType.isArray()) {
>                     Class<?> componentType = paramType.getComponentType();
>                     List<Object> setterValueArray = arraySetters.get(aMethod);
>                     if (setterValueArray == null) {
>                         setterValueArray = new ArrayList<Object>();
>                         arraySetters.put(aMethod, setterValueArray);
>                     }
>                     
>                     /*********************** Fix Starts 
> *************************/
>                     // Old code commented out:
>                     // setterValueArray.add(createJavaObject(fieldValue, 
> componentType, context));
>                     
>                     // New code added:
>                     List<T> childElements = getChildElements(fieldValue);
>                     
>                     for (int i = 0; i < childElements.size(); i++)
>                      if (!isTextElement(childElements.get(i))) 
> setterValueArray.add(createJavaObject(childElements.get(i), componentType, 
> context));
>                     /*********************** Fix Ends 
> *************************/
>                 } else {
>                     aMethod.invoke(javaInstance, new Object[] 
> {createJavaObject(fieldValue,
>                                                                               
>    paramType,
>                                                                               
>    context)});
>                 }
>                 methodNotFound = false;
>             }
>         }
>         if (methodNotFound) {
>             XML2JavaMapperException xml2JavaEx =
>                     new XML2JavaMapperException("No field or setter method to 
> configure xml data");
>             xml2JavaEx.setJavaFieldName(fieldName);
>             xml2JavaEx.setJavaType(javaType);
>             throw xml2JavaEx;
>         }
>     }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to