You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by vijay venkataraman <vi...@ltp.soft.net> on 2006/03/14 10:08:46 UTC

Map backed actionForm and pushing multiselect value in the map

|Hi,

I have a Form bean backed by a Map.
I want to capture the responses of the input fields in the jsp in to this Map.

When the selected values results into Array(String[]) in case of Multiselect only the first 
value in the array gets in to this map as a value. This is the case with radio buttons having same names.

My action form bean is a copy of the bean given in struts document.

public FooForm extends ActionForm {

    private final Map values = new HashMap();

    public void setValue(String key, Object value) {
        values.put(key, value);
    }

    public Object getValue(String key) {
        return values.get(key);
    }

}

Here is the JSP fragment
<html-el:select multiple="true" property="value('5')">
  <html-el:option value="one">ONE</html-el:option>
  <html-el:option value="two">TWO</html-el:option>
</html-el:select>


When the JPS page is rendered i am able to see the value 
as ONE and TWO for my multiselect. Now in the UI when i select ONE and TWO, 
only one value that is the first one in index zero is part
of the map.

I debugged it and found that this is handled by ||setProperty(Object bean, 
String name, Object value)|| in bean util class. I have cut, pasted the 
code at the end of mail for quick reference and using that as 
context to explain the problem. 
||
Starting from the point ||HERE>>>START (Look for it in code below)
||||The obtained descriptor is|| instanceof MappedPropertyDescriptor.|
|
Now look for the comments HERE>>> - From this point all 
idenfitcation for setting up the value takes place.
At this point the type.isArray fails, the obtained value is: 
type = java.lang.Object<T> (The return type for getValue)
||value = String["ONE", "TWO"] - This comes out fine.

The code skips condition :  HERE>>>1 (||if (type.isArray() && (index < 0))||) 
and goes through to HERE>>>3  (||if ((value instanceof String) || (value == null))||)

||If it is a instance of MappedPropertyDescriptor then why cant 
the value be pushed as is? Why do we need the check for 
type.isArray()? for the case of MappedPropertyDescriptor|
|
I am not sure whether my coding of form bean is wrong or if the 
jsp is wrong, i thought i could generically add objects in to the map.
||||||
||I am working with dynamic form fields, which can be of any type,
(html radio,checkbox, input, multiselect), hence i thought i can
get it resolved using map based ActionForms, but the problem is 
that only the first item in the array gets into the map. Can anyone let
me know what the mistake is?

I have gone through different posts where user have said use bean method
of the form String[] getValue() and setValue(index, String[]). I am not
convinced. If bean utils can be tweaked, the problem can be resolved.

Using struts 1.2.4 
Note : I tried with the latest version of bean utils and the bean utils that comes with 1.2.4. 

||Is there a better way to address my requirements. 
||Any pointers will be higly appreciated.

The code:
---------
||
public void setProperty(Object bean, String name, Object value)
        throws IllegalAccessException, InvocationTargetException {

        // Trace logging (if enabled)
        if (log.isTraceEnabled()) {
            StringBuffer sb = new StringBuffer("  setProperty(");
            sb.append(bean);
            sb.append(", ");
            sb.append(name);
            sb.append(", ");
            if (value == null) {
                sb.append("<NULL>");
            } else if (value instanceof String) {
                sb.append((String) value);
            } else if (value instanceof String[]) {
                String values[] = (String[]) value;
                sb.append('[');
                for (int i = 0; i < values.length; i++) {
                    if (i > 0) {
                        sb.append(',');
                    }
                    sb.append(values[i]);
                }
                sb.append(']');
            } else {
                sb.append(value.toString());
            }
            sb.append(')');
            log.trace(sb.toString());
        }

        // Resolve any nested expression to get the actual target bean
        Object target = bean;
        int delim = findLastNestedIndex(name);
        if (delim >= 0) {
            try {
                target =
                    getPropertyUtils().getProperty(bean, name.substring(0, delim));
            } catch (NoSuchMethodException e) {
                return; // Skip this property setter
            }
            name = name.substring(delim + 1);
            if (log.isTraceEnabled()) {
                log.trace("    Target bean = " + target);
                log.trace("    Target name = " + name);
            }
        }

        // Declare local variables we will require
        String propName = null;          // Simple name of target property
        Class type = null;               // Java type of target property
        int index = -1;                  // Indexed subscript value (if any)
        String key = null;               // Mapped key value (if any)

        // Calculate the property name, index, and key values
        propName = name;
        int i = propName.indexOf(PropertyUtils.INDEXED_DELIM);
        if (i >= 0) {
            int k = propName.indexOf(PropertyUtils.INDEXED_DELIM2);
            try {
                index =
                    Integer.parseInt(propName.substring(i + 1, k));
            } catch (NumberFormatException e) {
                ;
            }
            propName = propName.substring(0, i);
        }
        int j = propName.indexOf(PropertyUtils.MAPPED_DELIM);
        if (j >= 0) {
            int k = propName.indexOf(PropertyUtils.MAPPED_DELIM2);
            try {
                key = propName.substring(j + 1, k);
            } catch (IndexOutOfBoundsException e) {
                ;
            }
            propName = propName.substring(0, j);
        }

        // Calculate the property type
        if (target instanceof DynaBean) {
            DynaClass dynaClass = ((DynaBean) target).getDynaClass();
            DynaProperty dynaProperty = dynaClass.getDynaProperty(propName);
            if (dynaProperty == null) {
                return; // Skip this property setter
            }
            type = dynaProperty.getType();
        } else {
            PropertyDescriptor descriptor = null;
            try {
                descriptor =
                    getPropertyUtils().getPropertyDescriptor(target, name);
                if (descriptor == null) {
                    return; // Skip this property setter
                }
            } catch (NoSuchMethodException e) {
                return; // Skip this property setter
            }
            HERE>>>START
            if (descriptor instanceof MappedPropertyDescriptor) {
                if (((MappedPropertyDescriptor) descriptor).getMappedWriteMethod() == null) {
                    if (log.isDebugEnabled()) {
                        log.debug("Skipping read-only property");
                    }
                    return; // Read-only, skip this property setter
                }
                type = ((MappedPropertyDescriptor) descriptor).
                    getMappedPropertyType();
            } else if (descriptor instanceof IndexedPropertyDescriptor) {
                if (((IndexedPropertyDescriptor) descriptor).getIndexedWriteMethod() == null) {
                    if (log.isDebugEnabled()) {
                        log.debug("Skipping read-only property");
                    }
                    return; // Read-only, skip this property setter
                }
                type = ((IndexedPropertyDescriptor) descriptor).
                    getIndexedPropertyType();
            } else {
                if (descriptor.getWriteMethod() == null) {
                    if (log.isDebugEnabled()) {
                        log.debug("Skipping read-only property");
                    }
                    return; // Read-only, skip this property setter
                }
                type = descriptor.getPropertyType();
            }
        }
        // HERE>>>
        // Convert the specified value to the required type
        Object newValue = null;
        // HERE>>>1
        if (type.isArray() && (index < 0)) { // Scalar value into array
            if (value == null) {
                String values[] = new String[1];
                values[0] = (String) value;
                newValue = getConvertUtils().convert((String[]) values, type);
            } else if (value instanceof String) {
                String values[] = new String[1];
                values[0] = (String) value;
                newValue = getConvertUtils().convert((String[]) values, type);
            } else if (value instanceof String[]) {
                newValue = getConvertUtils().convert((String[]) value, type);
            } else {
                newValue = value;
            }
        } else if (type.isArray()) {         
            // HERE>>>2
            // Indexed value into array
            if (value instanceof String) {
                newValue = getConvertUtils().convert((String) value,
                                                type.getComponentType());
            } else if (value instanceof String[]) {
                newValue = getConvertUtils().convert(((String[]) value)[0],
                                                type.getComponentType());
            } else {
                newValue = value;
            }
        } else {
             // HERE>>>3
             // Value into scalar
            if ((value instanceof String) || (value == null)) {
                newValue = getConvertUtils().convert((String) value, type);
            } else if (value instanceof String[]) {
                newValue = getConvertUtils().convert(((String[]) value)[0],
                                                type);
            } else if (getConvertUtils().lookup(value.getClass()) != null) {
                newValue = getConvertUtils().convert(value.toString(), type);
            } else {
                newValue = value;
            }
        }

        // Invoke the setter method
        try {
            if (index >= 0) {
                getPropertyUtils().setIndexedProperty(target, propName,
                                                 index, newValue);
            } else if (key != null) {
                getPropertyUtils().setMappedProperty(target, propName,
                                                key, newValue);
            } else {
                getPropertyUtils().setProperty(target, propName, newValue);
            }
        } catch (NoSuchMethodException e) {
            throw new InvocationTargetException
                (e, "Cannot set " + propName);
        }

    }



Thanks,
Vijay
|


------------------------------DISCLAIMER------------------------------
This message is for the named person's use only. It may contain 
confidential, proprietary or legally privileged information. No
confidentiality or privilege is waived or lost by any mistransmission. 

If you receive this message in error, please immediately delete it and 
all copies of it from your system, destroy any hard copies of it and 
notify the sender. You must not, directly or indirectly, use, disclose, 
distribute, print, or copy any part of this message if you are not the 
intended recipient. 

Lisle Technology Partners Pvt. Ltd. and any of its subsidiaries each 
reserve the right to monitor all e-mail communications through its 
networks. 

Any views expressed in this message are those of the 
individual sender, except where the message states otherwise and the 
sender is authorized to state them to be the views of any such entity.