0

Say I have a class and a method named testMethod(String test1, String test 2). I also have another class with different method which will call which ever method it is in. See the example below

public class functional {

    testMethod(String test1, String test2) {

        reCallMethod();

    }
}

reCallMethod(){
    testMethod(test1, test2); // ------> This has to be dynamic. I've written the method name as "testMEthod" here. But I want it generalized so that I can use this in any method and not just in "testMethod"
}

More information :-------------------------------

public class test1 {
public void TestCase1(String param1, String param2, String param3) {
        try {
            //Bla Bla Bla
        }
        catch (Throwable t) {
                TestCase_Store_Locator_Verify_Page_Name(param1,param2,param3); //Retry running this method

        }
    }
}

public class test2 {
    public void TestCase2(String param1, String param2, String param3, String param4, String Param5) {
        try {
            //Bla Bla Bla
        }
        catch (Throwable t) {
                TestCase2(param1,param2,param3,param4,param5); //Retry running this method

        }
    }
}

Like TestCase1 and TestCase2 I have 500 Tests. Instead of doing above I will have a common method called retryLogic like below

public void retryLogic(){
 //Call the test method in the class which this method is placed.
}


So my TestCase1 will look like

    public class test1 {
public void TestCase1(String param1, String param2, String param3) {
        try {
            //Bla Bla Bla
        }
        catch (Throwable t) {
                retryLogic(); //Retry running this method

        }
    }
}


    public void TestCase2(String param1, String param2, String param3) {
        try {
            //Bla Bla Bla
        }
        catch (Throwable t) {
                retryLogic(); //Retry running this method

        }
    }
}
Damien-Amen
  • 7,232
  • 12
  • 46
  • 75
  • It looks like you are looking for [reflection](http://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html). – Pshemo Jan 23 '13 at 20:29
  • Why does it _have_ to be dynamic? – Louis Wasserman Jan 23 '13 at 20:46
  • Note that in java, classes, by convention, have names beginning with upper case and methods have names beginning with lower case. Most everyone follows these conventions. – Lee Meador Jan 23 '13 at 21:54
  • If you use reflection, you will have to pass the parameters into the retry function any way you cut it. This is because parameters only have scope within their own function and reflection moves the re-call of the function outside that scope. – Lee Meador Jan 23 '13 at 22:04
  • You should definitely follow standard naming Java convention. Classes should start with a capital letter, and methods with a lower case method. – Laf Jan 23 '13 at 22:26

6 Answers6

1

You can use Reflection to determine which method to call at run-time.

See this post for information on how to do that: How do I invoke a Java method when given the method name as a string?

Community
  • 1
  • 1
Pat Burke
  • 580
  • 4
  • 13
1

Have a look at Java's Reflection feature!

tttthomasssss
  • 5,852
  • 3
  • 32
  • 41
  • Thank You! But in my example I have "testMethod" accepting two parameters. But what if I have another method called "testMethod2" which accepts three parameter and I still want to use "reCallMethod" ? – Damien-Amen Jan 23 '13 at 20:50
  • you can do that with reflection, have a look at Method's [invoke](http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object,%20java.lang.Object...)) method, it accepts a variable number of parameters. at runtime, of course you do need to know which method to call and how many parameters it takes. – tttthomasssss Jan 23 '13 at 20:56
  • Can you pls check my edited information now and see if you can help me? Thanks! – Damien-Amen Jan 23 '13 at 21:37
  • in your retryLogic method you need to pass the method you want to invoke along with an array of its parameters. when you call retryLogic you can get the correct method with this.getClass().getMethod("TestCase2", String.class, String.class, String.class). you pass this method, along with the object you invoke it on and its parameters to retryLogic. in there you do myMethod.invoke(obj, param1, param2); – tttthomasssss Jan 23 '13 at 21:55
0

You can use Java reflection to lookup the methods on a class. So, clazz.getMethods() will return an Array of Method objects. When you identify the one you're interested in, you would call method.invoke(...) See this: http://docs.oracle.com/javase/tutorial/reflect/class/classMembers.html

Darius X.
  • 2,886
  • 4
  • 24
  • 51
0

In java there is no way of having a variable holding a reference to a method. Some other languages, for example javascript, allow this.

There is a verbose workaround to this if you pass an object into the 'reCallMethod()' that implements an interface with a known method name. Usually the interface looks something like this:

public interface CallMe() {
    public Object execute(Object parm1, Object parm2);
}

though the return value and the parameters on 'execute' may vary depending no your needs.

Then your code looks something like this:

public class functional {

    final OtherClass otherInstance = new OtherClass();

    testMethod(String test1, String test2) {

        reCallMethod(new CallMe() {
            public Object execute(Object parm1, Object par2) {
                return otherInstance.varyingMethod((String)parm1, (String)parm2); // This is the varying method
            }
        }, text1, text2);
    });
}

reCallMethod(CallMe func, Object parm1, Object parm2){
    func.execute(parm1, parm2);
}
Lee Meador
  • 12,829
  • 2
  • 36
  • 42
0

If you do not want to use reflexion, there's another possibility, which is the Strategy pattern. It does not provide exactly the same capabilities as the reflexion, but you do get the possibility to change which method you call at runtime. You can use a class that will call the correct method in your functional class.

For example, if your functional class have the following definition:

public class functional {
    public void testMethod (String test1, String test2) {
        reCallMethod();
    }

    public void anotherMethod (String test1, String test2) {
        reCallMethod();
    }
}

You could have an interface which would define your strategy interface:

public interface MyStrategy {
    void callMethod (String param1, String param2);
}

Then have 2 different strategies implementation; one for each method you want to call. For example:

public class TestMethodStrategy implements MyStrategy {
    private functional myFunctional;

    public TestMethodStrategy (functional myFunctional) {
        this.myFunctional = myFunctional;
    }

    public void callMethod (String test1, String test2) {
        myFunctional.testMethod (test1, test2);
    }
}

All you need to do afterwards is use the appropriate strategy depending on the current context.

Laf
  • 7,965
  • 4
  • 37
  • 52
0

Maybe you could just do this which does the same thing:

  public void TestCase2(String param1, String param2, String param3) {
        boolean success;
        do {
            success = true;
            try {
                //Bla Bla Bla
            }
            catch (Throwable t) {
                success = false;
            }
        } while (!success);
    }

You could even add a counter to keep it from running forever. Just something that increments and does a break after 20 tries or whatever.

The big plus about it is that, if you already have the other code written. You just copy and past the 1st 4 lines at the top of the method and copy and past the last 5 lines at the bottom and make a check that none of the exceptions are getting caught and eaten inside the existing code.

Lee Meador
  • 12,829
  • 2
  • 36
  • 42