Return-Path: Delivered-To: apmail-jakarta-commons-dev-archive@www.apache.org Received: (qmail 9310 invoked from network); 18 Jan 2005 22:22:14 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 18 Jan 2005 22:22:14 -0000 Received: (qmail 19488 invoked by uid 500); 18 Jan 2005 22:22:09 -0000 Delivered-To: apmail-jakarta-commons-dev-archive@jakarta.apache.org Received: (qmail 19405 invoked by uid 500); 18 Jan 2005 22:22:08 -0000 Mailing-List: contact commons-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Jakarta Commons Developers List" Reply-To: "Jakarta Commons Developers List" Delivered-To: mailing list commons-dev@jakarta.apache.org Received: (qmail 10336 invoked by uid 99); 18 Jan 2005 22:17:00 -0000 X-ASF-Spam-Status: No, hits=0.0 required=10.0 tests= X-Spam-Check-By: apache.org Received-SPF: pass (hermes.apache.org: local policy) Message-ID: <000701c4fdab$6be8a460$6401a8c0@inforise.org> Reply-To: "Mark Rines" From: "Mark Rines" To: Subject: BeanUtilsBean setProperty conversion not allowing String[] to Object Date: Tue, 18 Jan 2005 16:16:03 -0600 MIME-Version: 1.0 Content-Type: text/plain; format=flowed; charset="iso-8859-1"; reply-type=original Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2900.2180 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2180 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - ssa2.serverconfig.com X-AntiAbuse: Original Domain - jakarta.apache.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - inforise.com X-Source: X-Source-Args: X-Source-Dir: X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N I'm having a hard time understanding the philosophy behind org.apache.commons.beanutils.BeanUtilsBean's setProperty(Object bean, String name, Object value) method. There seems to be a design decision to eliminate the inheritance of arrays from Object. I looked through bugzilla on issues.appache.org and found id=16525 and 32874 interesting and somewhat related but I guess I still don't get it. Here is the background: I'm using commons-beanutils-1.7.0 in a Struts 1.2.x application. My program has the following form (bean): public class MyForm extends ActionForm{ Object o = null; public void setObject(Object toSet){ o = toSet; } public Object getObject(){ return o; } Given that an array is an Object, you should be able to: String t = "test"; String[] sa = {t,t}; MyForm myForm = new MyForm(); HashMap map = new HashMap(1); map.put("object",sa); BeanUtils.populate(myForm,map); //myForm.setObject(sa); // cause this line works you then should be able to successfully compile and execute: String[] sa2 = (String[])myForm.getObject(); assert(sa[0].equals(t)); assert(sa[1].equals(t)); Instead I'm getting no sa[1] from getObject() and o is now a simple String with value "test". My discovery: BeanUtilsBean.setProperty reflects the myForm.setObject method and assumes property Object is scalar; which is an invalid assumption as Object could be an array. It appears that setProperty then "converts" the sa String array to a simple String using the first element of the array (hardcoded 0) and drops the rest of the array. This is lossy at best and quietly violates "data-in equals data-out". This lossy behavior can be traced to lines 1003-1005 in BeanUtilsBean's setProperty method as follows: } else if (value instanceof String[]) { newValue = getConvertUtils().convert(((String[]) value)[0], type); Again, the above code appears to render invalid the inheritance of arrays from Object and precludes me from writing a Converter for String[] to Object. Suggested fix: BeanUtilsBean.setProperty should reflect the named property's set method and check if sa (the String[] argument) is an instanceof Object (the set method's parameter type) and simply pass the array into the set method unchanged. What would be the impact of changing line 1003-5 in BeanUtilsBean from: } else if (value instanceof String[]) { newValue = getConvertUtils().convert(((String[]) value)[0], type); to something like: } else if (value instanceof String[] && !(value instanceof type) ) { newValue = getConvertUtils().convert(((String[]) value)[0], type); ??? I realize the design allows for making my own Converter and registering with ConvertUtils but it is not obvious to me how I can circumnavigate the intrinsic assumption that Object is scalar. Besides, adding conversions for common types to their parents seems to add unnecessarily to maintenance costs, violate the principles of OO and limits the flexibilty of polymorphism. I anxiously await work-arounds, debate, criticism, alternative solutions, pointers, hacks, etc... Mark Rines --------------------------------------------------------------------- To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: commons-dev-help@jakarta.apache.org