BeanUtils uses the Introspector (core java) to populate your beans. It will use 
your setXs(index, object) and getXs(index) methods if you supply them (see 
http://java.sun.com/j2se/1.4.2/docs/api/java/beans/IndexedPropertyDescriptor.html).
 Since HashSet does not guarantee the order of your set will remain constant, 
I'd use a java.util.LinkedHashSet if I was you.

If you provide the implementation for the following methods, you should be fine.

public class Role extends ValidatorActionForm  {
   private Set users = new LinkedHashSet();

   public Set getUsers() {}
   public void setUsers(Set users) {}
   public String getUsers(int index) {}
   public void setUsers(int index, String user) {}
}

Another simpler option is to use a List or an array on your form and move it to 
a Set when you process it in your middle tier.

Lance.
-----Original Message-----
From: Abbas Adel [mailto:[EMAIL PROTECTED] 
Sent: 02 February 2007 23:55
To: commons-user@jakarta.apache.org
Subject: Struts+Hibernate many-to-many mismatch

Dears,

 

I have 2 hibernate entities, user & role, with many-to-many relation. I also
use them as form beans.

 

[code]

public class User extends ValidatorActionForm {

    

   private int UID;

   private String username;

   private String password;

   private String name;

   private String email;

   private Set roles;

.

}

 

public class Role extends ValidatorActionForm  {

    

   private int RID;

   private String name;

   private Set users;

.

}

[/code]

 

I created a simple Struts form to insert new user

 

[code]

<html:form action="/InsertUser" method="post">

            Username:  <html:text property="username" />

            Password:   <html:password property="password" />

            Name:          <html:text property="name" />

            Email:           <html:text property="email" />

            Roles: 

           <html:select property="roles" multiple="true"> 

                <html:optionsCollection name="roles" label="name"
value="RID" />

            </html:select>

            <html:submit/>

</html:form>

[/code]

 

When I run this form, struts complains [i]"argument type mismatch" [/i]
because it doesn't know how to convert the roles property, which is
String[], into java.util.Set

 

I had to write my own BeanUtil type convertor to convert from String[] to
java.util.Set. 

[code]

public class RolesListConverter extends AbstractArrayConverter  {

    

    public Object convert(Class type, Object value) {

        

        try {

            List list = parseElements(value.toString());

            String results[] = new String[list.size()];

            Set results = new HashSet(list.size());

            for (int i = 0; i < list.size(); i++) {

                results[i] = (String) list.get(i);

                results.add(Role (Integer.parseInt((String)list.get(i))));

            }

            return (results);

        } catch (Exception e) {

            if (useDefault) {

                return (defaultValue);

            } else {

                throw new ConversionException(value.toString(), e);

            }

        }

    }

}

[/code]

 

Then struts didn't complain but the roles Set was populated with 1 role only
regardless of how many roles were selected.

I gave a closer look at org.apache.commons.beanutils.BeanUtilsBean.java to
see how it works. I found this:

[code]

else if (type.isArray()) {         // 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());

[/code]

 

Because java.util.Set is not an array "Set.class.isArray() return false"
then treat the "String[] value" as a single-value array "value[0]"

 

So, what do you suggest to force struts to convert String[] to Set?

 

Thanks in advance

BISO

Student @ Menufia University

 

org.apache.commons.beanutils.BeanUtilsBean.java

[code]

.

976 

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()) {         // Indexed value into array

            if (value instanceof String) {

                newValue = getConvertUtils().convert((String) value,
type.getComponentType());

            } else if (value instanceof String[]) {

1004                newValue = getConvertUtils().convert(((String[])
value)[0], type.getComponentType());

            } else {

                newValue = value;

            }

        } else {                             // 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;

            }

        }

.

[/code]



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

Reply via email to