2

I'm following this article on Oracle Network to implement MVC when developing desktop applications. I have a problem, though: I'm using an abstract Directory class extended by SimpleDirectory and WildcardDirectory. One of the model manager method accepts a Directory as argument:

public void addDirectoryDummy(Directory d){
    System.out.println("Hello!");
}

The abstract controller uses a setModelProperty to call this method:

protected void setModelProperty(String propertyName, Object newValue) {



    for (AbstractModel model: registeredModels) {
        try {

            Method method = model.getClass().
                getMethod(propertyName, new Class[] {
                                                  newValue.getClass()
                                              }
                         );

            method.invoke(model, newValue);

        } catch (Exception ex) {
           ex.printStackTrace();
        }
    }
}

I call it from my actual controller like this:

public void dummy( Directory d){
    setModelProperty( BACKUP_DUMMY, d );
}

In my view I have:

this.controller.dummy( new SimpleDirectory(0,"ciao") );

I have the following error:

java.lang.NoSuchMethodException: it.univpm.quickbackup.models.BackupManager.addDirectoryDummy(it.univpm.quickbackup.models.SimpleDirectory)
    at java.lang.Class.getMethod(Class.java:1605)

How do I solve this problem? I'm missing something in the usage of getMethod.

EDIT: I've read the docs and in getMethod it says

The parameterTypes parameter is an array of Class objects that identify the method's formal parameter types, in declared order.

So I'm guessing that's the problem.

dierre
  • 7,140
  • 12
  • 75
  • 120

2 Answers2

3
public class Test
{
    public static void main(String[] args) throws Exception { 
        Test test = new Test();
        Child child = new Child();

        // Your approach, which doesn't work
        try {
            test.getClass().getMethod("doSomething", new Class[] { child.getClass() });

        } catch (NoSuchMethodException ex) {
            System.out.println("This doesn't work");
        }

        // A working approach
        for (Method method : test.getClass().getMethods()) {
            if ("doSomething".equals(method.getName())) {
                if (method.getParameterTypes()[0].isAssignableFrom(child.getClass())) {
                    method.invoke(test, child);
                }
            }
        }
        System.out.println("This works");

    }

    public void doSomething(Parent parent) {

    }
}

class Parent {

}

class Child extends Parent {

}
adrianboimvaser
  • 2,651
  • 1
  • 22
  • 30
  • The problem this is a general controller. I can't do that, I need to know the class at runtime. And second of all, SimpleDirectory extends Directory so isn't there a solution when it comes to inheritance? – dierre Jan 19 '11 at 16:36
  • Have a look at this post: http://stackoverflow.com/questions/2169497/unexpected-class-getmethod-behaviour – adrianboimvaser Jan 19 '11 at 16:43
  • 1
    tnx, I've read it but I don't think it's the same because he's talking about interfaces, I'm having trouble with inheritance. It doesn't seem to me that isAssignableFrom would solve my problem. – dierre Jan 19 '11 at 16:47
  • As soon as I go home I'll try and let you know. – dierre Jan 19 '11 at 18:19
  • `method.getParameterTypes()[0].isAssignableFrom(child.getClass())` can be written as `method.getParameterTypes()[0].isInstance(child)` – user102008 Aug 16 '11 at 01:18
0
package com.test;

import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws Exception {
    Test test = new Test();
    Child child = new Child();

    // Your approach, which doesn't work
    try {
        Method method = test.getClass().getMethod("doSomething", new Class[] { child.getClass().getSuperclass() });
        method.invoke(test, child);
        System.out.println("This works");
    } catch (NoSuchMethodException ex) {
        System.out.println("This doesn't work");
    }

    // A working approach
    for (Method method : test.getClass().getMethods()) {
        if ("doSomething".equals(method.getName())) {
        if (method.getParameterTypes()[0].isAssignableFrom(child.getClass())) {
            method.invoke(test, child);
            System.out.println("This works");
        }
        }
    }

    }

    public void doSomething(Parent parent) {

    }
}

class Parent {

}

class Child extends Parent {

}

You need add .getSuperclass() to child

Stéphane GRILLON
  • 11,140
  • 10
  • 85
  • 154