I'm using Grails with third-party java libraries, and I'd like to override behavior in one of those libraries.
I've attempted to do this in Bootstrap.groovy, like so:
// class overrides
ExpandoMetaClass.enableGlobally()
SimpleStringFilter.metaClass.passesFilter = {Object itemId, Item item ->
final Property<?> p = item.getItemProperty(propertyId);
if (p == null) {
return false;
}
Object propertyValue = p.getValue();
if (propertyValue == null) {
return false;
}
final String value = ignoreCase ? propertyValue.toString()
.toLowerCase() : propertyValue.toString();
if (onlyMatchPrefix) {
if (!value.startsWith(filterString)) {
return false;
}
} else {
if (!value.contains(filterString)) {
return false;
}
}
return true;
}
I know for a fact that the method passesFilter in the SimpleStringFilter class gets called, but I've set a breakpoint in my code above and it's never hit.
For reference, the signature of the java method is:
public boolean passesFilter(Object itemId, Item item)
So, can one actually override behavior in java libraries with ExpandoMetaClass globally? Can someone explain the behavior and nuances of using it in this way?
Thanks!
The issue you are facing is that Java classes don't invoke metaClass
. Groovy can't override method calls to Java classes using metaClass
.
This is a common misunderstanding when you see something like this:
def object = new MyJavaObject()
object.metaClass.someMethod = { ... }
What is actually happening above is you are creating a Groovy object that wraps the MyJavaObject
which then allows that instance to invoke through metaClass.