click-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Bob Schellink <sab...@gmail.com>
Subject Re: "Wrong Number of Arguments" Error in Form.copyTo()
Date Mon, 20 Oct 2008 05:31:36 GMT
Hmm nasty. Are you using JDK 1.4 or 1.5?

Perhaps you have a getter which accepts an argument? That would 
certainly throw IllegalArgumentException too.

Anyway I think we need to improve the exception handling a bit to 
provide more information for debugging.

Below is my proposed change to ContainerUtils#ensureObjectPathNotNull.

If you can replace the method with the one below it should provide 
better info on which method with what parameter
is giving problems.

Let me know if this shed some light on the issue.


 private static void ensureObjectPathNotNull(Object object, String path) {

        final int index = path.indexOf('.');

        if (index == -1) {
            return;
        }

        String value = path.substring(0, index);
        String getterName = ClickUtils.toGetterName(value);
        String isGetterName = ClickUtils.toIsGetterName(value);

        Method foundMethod = null;
        Method[] methods = object.getClass().getMethods();
        for (int i = 0; i < methods.length; i++) {
            String name = methods[i].getName();
            if (name.equals(getterName)) {
                foundMethod = methods[i];
                break;

            } else if (name.equals(isGetterName)) {
                foundMethod = methods[i];
                break;
            }
        }

        if (foundMethod == null) {
            String msg =
                "Getter method not found on class : " + object.getClass()
                + " for path value : " + value;
            throw new RuntimeException(msg);
        }

        try {
            Object result = foundMethod.invoke(object, new Object[0]);

            if (result == null) {
                result = foundMethod.getReturnType().newInstance();

                String setterName = ClickUtils.toSetterName(value);
                Class[] classArgs = { foundMethod.getReturnType() };

                Method setterMethod =
                    object.getClass().getMethod(setterName, classArgs);

                Object[] objectArgs = { result };

                setterMethod.invoke(object, objectArgs);
            }

            String remainingPath = path.substring(index + 1);

            ensureObjectPathNotNull(result, remainingPath);

        } catch (Exception e) {
            HtmlStringBuffer buffer = new HtmlStringBuffer();
            Class[] parameterTypes = foundMethod.getParameterTypes();
            buffer.append("(");
            if (parameterTypes != null) {
                for (int i = 0; i < parameterTypes.length; i++) {
                    buffer.append(parameterTypes[i].getName());
                    if (i < parameterTypes.length - 1) {
                        buffer.append(", ");
                    }
                }
            }
            buffer.append(")");
            String msg = "Error occurred while ensuring path is not null 
for"
                + " class : " + object.getClass() + ", method : "
                + foundMethod.getName() + buffer.toString() + " and 
return type : "
                + foundMethod.getReturnType();
            throw new RuntimeException(msg, e);
        }
    }




Alvin Townsend wrote:
> Hi Bob,
>
> That largely is the behavior I observe everywhere else in the
> application. For reasons unknown, just in this one place, we get this
> error. (Even odder is that I cannot replicate the error in my IDE,
> (Ganymede) only when packaged and deployed to Tomcat.)
>
> Thank you much for the help!
>
> Alvin
>
> On Sun, Oct 19, 2008 at 3:42 PM, Bob Schellink <sabob1@gmail.com> wrote:
>   
>> Alvin Townsend wrote:
>>     
>>> Hi Bob,
>>>
>>> That makes a lot of sense. Many of our objects cannot be instantiated
>>> without arguments to the Constructors, so I've made sure that all of
>>> them were set up previously and that the Form.copyTo wouldn't come
>>> across anything null.
>>>
>>>       
>> Here is some more info. Click calls the getter method of the path to figure
>> out whether to instantiate
>> a new instance or not.
>>
>> field = new TextField("address.street");
>> form.copyTo(client);
>>
>> From the above Click will tokenize the field path into "address" and
>> "street". Next it will try and check if
>> address is null through reflection by invoking the address getter:
>>
>> client.getAddress();
>>
>> If client.getAddress returns null Click tries and instantiates the Address.
>>
>> If you use a debugger you can place a breakpoint roughly on line 595 of
>> class net.sf.click.util.ContainerUtils#ensureObjectPathNotNull.
>> If your breakpoint is hit, it means Click tries to instantiate a object...
>>
>> kind regards
>>
>> bob
>>
>>
>>
>>
>>     
>
>   


Mime
View raw message