Hi,
Sorry if you receive this twice. I didn't see this mail for more than
4 hours after sending it.
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 fields 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 and pasted the code at the end of mail for quick reference
and using that as context to explain the problem.
The obtained descriptor is instanceof MappedPropertyDescriptor.|
|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 and goes through HERE>>>3
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?
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.
Any pointers will be higly appreciated. Kindly cc to me:
vijay <[EMAIL PROTECTED]> since i am not member of the users list.
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
}
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
|