ExpandoMetaClass in Grails to override behavior in a Java library?

337 Views Asked by At

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!

1

There are 1 best solutions below

1
On BEST ANSWER

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.