Dynamic Method Calls with Groovy
Thanks to some help from James Lorenzen, Chad Gallemore and Travis Chase, ...
A couple of days ago I found myself iterating through a set of key=value pairs, and for each one calling a setter method on another object. In order to know which setter method to call, I had to examine the key. That's when it hit me... What if I could use the key to generate the setter method to call. Check this out.
I've got a simple bean with 2 member variables: username and password. There are corresponding setter methods: setUsername() and setPassword().
class UserBean {
private String username;
private String password;
void setUsername(String username) {
this.username = username
}
void setPassword(String password) {
this.password = password
}
}
Here I have a HashMap that I want to iterate through. It just so happens the keys in the map entries correspond exactly to the member variables of my simple bean. So, instead of examining each key to decide what setter method to call, I can do this:
import junit.framework.TestCase
public class DynamicMethodBuildingTest extends TestCase {
void testBuildMethodsBasedOnMapKeys() {
def testMap = new HashMap();
testMap.put("username","chad")
testMap.put("password","asdfasdf")
def userbean = new UserBean();
testMap.entrySet().each { entry ->
userbean."$entry.key" = entry.value
}
}
}
At this point I'm not really building the method that is being called. I'm building the property name. So, let's look at actually building a method call.
I've added 2 methods to my UserBean: login() and logoff().
void login() {
println username + " has Logged In"
}
void logoff() {
println username + " has Logged Off"
}
Let's test calling these 2 methods dynamically.
void testExecuteUserAction() {
def userActions = ["login", "logoff"];
def userbean = new UserBean()
userbean.username = "chad"
userActions.each { action ->
userbean."$action"()
}
}
Here's the output:
chad has Logged In
chad has Logged Off
Well, that's all it takes. And if you're asking, "What about a method that takes parameters?"... simply put your parameters inside the parenthesis. It may look something like this:
userbean."$action"(username)
Now I wonder, what would it take to accomplish this in Java?