The challenge was a simple one: my method is passed in an object. This object may or may not have a certain method – called getClientListeners(). When it does, the method should be invoked and the result from the call must be returned by my method. If the object does not expose such a getClientListeners() method, my method should return null.
Sounds simple enough. However because the objects do not implement a common interface that specifies the method getClientListeners(), I found myself writing repeated if-clauses, for all the known Class that could be passed in to my method:
if (uiComponent instanceof RichInputText) { RichInputText uixComponent = (RichInputText)uiComponent; cls = uixComponent.getClientListeners(); if (cls == null) { cls = new ClientListenerSet(); uixComponent.setClientListeners(cls); } }
And that for a seriously large number of classes.
Then it hit me:
using the Reflection API I can still invoke a method generically on any object – without having to rely on the objects implementing some interface. With a little generic code leveraging Java Reflection, I could quickly cut many dozens of lines of code from my application. Besides, the application caters for any class that exposes the getClientListeners() method!
The new generic implementation of the code above looks like this
ClientListenerSet cls = null; // use reflection to invoke the getClientListeners method if it exists on this uiComponent Method[] allMethods = uiComponent.getClass().getDeclaredMethods(); for (Method m : allMethods) { String mname = m.getName(); if (mname.startsWith("getClientListeners")) { try { m.setAccessible(true); Object o = m.invoke(uiComponent); if (o instanceof ClientListenerSet) { cls = (ClientListenerSet)o; return cls; } // Handle any exceptions thrown by method to be invoked. } catch (InvocationTargetException x) { Throwable cause = x.getCause(); } catch (IllegalAccessException e) { } } } if (cls == null) { cls = new ClientListenerSet(); for (Method m : allMethods) { String mname = m.getName(); if (mname.startsWith("setClientListeners")) { try { Object o = m.invoke(uiComponent, cls); // Handle any exceptions thrown by method to be invoked. } catch (InvocationTargetException x) { Throwable cause = x.getCause(); } catch (IllegalAccessException e) { } } } }
Resources
Tutorial on the Java Reflection API: Invoking Methods
Hi,
A much simpler way is to call Class.getMethod() directly to get the Method instance:
Method m = uiComponent.getClass().getMethod(“getClientListeners”,null);
m.invoke(uiComponent);
This way the loop can be avoided.
Regards,
Saurabh