Changing Object.toString() dynamically in Groovy has no effect when calling Integer.toString() - groovy

I injected overridden method toString into Object.metaClass:
Object.metaClass.toString ={
System.out.println("the string is $delegate")
}
and I thought that following code will execute this method:
1500.toString()
But it didn't not,nothing was printed to the console. That is what exactly confuses me: if something goes bad, then an error is to throw out; if Object.metaClass.toString is found and invoked, then the message will turn up, but why it is not working? What happened inside?

This behavior is correct, because java.lang.Integer overrides Object.toString() with its own implementation. If your assumption was correct then it would mean that you can break overridden method by forcing to use an implementation from parent class.
Consider following Groovy script:
Object.metaClass.toString = {
System.out.println("the string is $delegate")
}
class GroovyClassWithNoToString {}
class GroovyClassWithToString {
#Override
String toString() {
return "aaaa"
}
}
new GroovyClassWithNoToString().toString()
new GroovyClassWithToString().toString()
1500.toString()
Runtime.runtime.toString()
When you run it you will see something like:
the string is GroovyClassWithNoToString#3a93b025
the string is java.lang.Runtime#128d2484
You can see that GroovyClassWithNoToString.toString() called Object.toString() method and its modified version, also Runtime.toString() calls Object.toString() - I picked this class as an example of pure Java class that does not override toString() method.
As you can see overriding toString() method from Object level makes sense for classes that base on Object.toString() implementation. Classes that provide their own implementation of toString() wont use your dynamically modified method. It also explains why following code works:
Object.metaClass.printMessage = {
System.out.println("Hello!")
}
1500.printMessage()
In this example we are adding a new method called printMessage() to Object class and all classes that don't override this method will use this dynamic method we just created. Integer class does not have method like that one so it's gonna print out:
Hello!
as expected.
Also keep in mind that toString() should return a String and it's better to not print anything to output inside this method - you can end up with nasty StackOverflowError caused by circular calls to toString() method.
UPDATE: How toString() method is being picked by Groovy runtime?
Let me show you under the hood what happens when we call following script:
Object.metaClass.toString = {
System.out.println("Hello!")
}
1500.toString()
and let's see what does Groovy during the runtime. Groovy uses Meta Object Protocol (MOP) to e.g. invoke any method called in a Groovy code. In short, when you call any Java or Groovy method it uses MOP as an intermediate layer to find an execution plan for a method - call it directly or use e.g. a method that was injected dynamically.
In our case we use plain Java class - Integer. In this case Groovy will create an instance of PojoMetaMethodSite class to meta class implementation for Java class - an Integer. Every meta method is executed using one of the Groovy groovy.lang.MetaClass implementation. In this case groovy.lang.MetaClassImpl is being used. One of the last methods that picks a method to execute is MetaClassImpl.getMethodWithCachingInternal(Class sender, CallSite site, Class [] params). If you put a breakpoint in the beginning of this method and run a script with a debugger, you will see that this method is executed with following parameters:
In line 1331 you can see that helper method called chooseMethod(e.name, methods, params) is being used:
cacheEntry = new MetaMethodIndex.CacheEntry (params, (MetaMethod) chooseMethod(e.name, methods, params));
This method is responsible for picking the right method to execute when we try to invoke toString() on Integer object. Let's get there and see what happens. Here is what this method implementation looks like:
/**
* Chooses the correct method to use from a list of methods which match by
* name.
*
* #param methodOrList the possible methods to choose from
* #param arguments
*/
protected Object chooseMethod(String methodName, Object methodOrList, Class[] arguments) {
Object method = chooseMethodInternal(methodName, methodOrList, arguments);
if (method instanceof GeneratedMetaMethod.Proxy)
return ((GeneratedMetaMethod.Proxy)method).proxy ();
return method;
}
Source: https://github.com/apache/groovy/blob/GROOVY_2_4_X/src/main/groovy/lang/MetaClassImpl.java#L3158
Now let's see what parameters are received when we call our script:
What is most interesting in our case is the first element of methodOrList.data. It's a method object of:
public java.lang.String java.lang.Integer.toString()
which is the method toString() that Integer class overrides from its parent class. Groovy runtime picks this method, because it is the most accurate from the runtimes point of view - it is the most specific method for Integer class provided. If there is no toString() method overridden at the class level (e.g. Runtime class example I mentioned earlier) then the best candidate for invoking toString() method is a ClosureMetaMethod provided by us in Object.metaClass.toString = .... I hope it gives you a better understanding of what happens under the hood.

I don't think you can override the Object.toString() that way.
But this works:
Integer.metaClass.toString = { ->
System.out.println("the string is $delegate")
}
https://groovyconsole.appspot.com/script/5077208682987520

Related

Any way to make reflection not bypass Groovy interceptors (invokeMethod)?

I've got a class that is wrapping objects with a proxy using Groovy's metaClass "getProperty" and "invokeMethod" methods. The proxy/wrapper lets me do lazy loading on the objects, only grab the data once the getter for a property has been called.
It works well when I actually use the getters, but I ran into a problem when I started trying to use Jackson to serialize the object (a secondary use case). I thought that Jackson would spin through all of the getter methods, which would invoke each of the getters and load all the data. But unlike when I call getters myself, when Jackson uses reflection to call the methods, my interceptor methods are not invoked, so all my data is still null.
I trace the call to my object in the Jackson library to this bit of code in the BeanPropertyWriter. The _accessorMethod.invoke(bean) call invokes the 'getter' method, but not the code in my proxy. I was able to recreate it in a unit test too outside of Jackson too.
Is there something I should implement in my Groovy proxy class that would capture those requests via the Method objects in reflection?
This is what my proxying code looks like:
static <T> T lazyProxyFor(T object) {
Class clazz = object.class
object.metaClass.getProperty = { String name ->
println "getting property $name"
def currentVal = clazz.metaClass.getMetaProperty(name).getProperty(delegate)
if (!currentVal) {
setProperty('testing') //normally this goes and gets data from my service
}
return currentVal
}
object.metaClass.invokeMethod = { String name, Object args ->
println "calling $name"
if (name ==~ /get[A-Z][a-zA-Z0-9_]*/ && args?.size() == 0) {
object[name.drop(3).uncapitalize()] // call the getProperty method
} else {
clazz.metaClass.getMetaMethod(name, args)?.invoke(delegate, args) //like the underlying object process the
}
}
return object
}
and this is the code I was testing with:
Address address = lazyProxyFor(Address)
address.class.declaredMethods.each{ method ->
if (method.name.startsWith('get')) {
method.invoke(address) //<-- if I run with this version I get no output
//address."$method.name"() //<-- if I run with this version I get two messages, one for each
//getter method and then the underlying property, presummably because
//groovy is more involved here, instead of reflection
}
}

Groovy's missingMethod is not called on a Closure's Delegate for implicit calls to non-GroovyObjects

A closure with a delegate that is not a groovy-object (e.g. coming from a normal java-library), will never call the 'methodMissing' object added to that delegate using it's metaclass, if the call is made 'implicit' (i.e. not calling it explicitly on 'delegate' within the closure.)
The code below does an explicit and an implicit call to a non-existing method; it does so on a Groovy-class instance, a GString and a non-groovy object. The only one that fails is the implicit call to a non-groovy-object (i.c. ArrayList).
(You can see and run the same code online:
https://groovyconsole.appspot.com/edit/5200829376102400)
Not sure if this is a bug or a limitation - references to methodMissing defined through metaClass are pretty scarce. Any insightful comments would be welcome.
class ClosureDelegate {
def testMissingMethod(def someObject) {
someObject.metaClass.methodMissing = { String name, args ->
println name
}
def closure = {
delegate.anything()
anything() // this one fails on non-groovyclasses
}
closure.delegate = someObject
closure.resolveStrategy = Closure.DELEGATE_ONLY
closure()
}
}
class TestObject {}
println "testing with TestObject"
new ClosureDelegate().testMissingMethod(new TestObject())
println "testing with GString"
new ClosureDelegate().testMissingMethod("${new Date()}")
println "testing with ArrayList"
new ClosureDelegate().testMissingMethod(new ArrayList())
testing with TestObject
anything
anything
testing with GString
anything
anything
testing with ArrayList
anything
Caught: groovy.lang.MissingMethodException: No signature of method: ClosureDelegate$_testMissingMethod_closure2.anything() is applicable for argument types: () values: []
Possible solutions: toString(), toString(), any(), any()
According to the ClosureMetaClass implementation, this behavior is expected. Take a look at the following part that starts at line 275 in that file:
switch (resolveStrategy) {
case Closure.TO_SELF:
break;
case Closure.DELEGATE_ONLY:
method = getDelegateMethod(closure, delegate, methodName, argClasses);
callObject = delegate;
if (method == null) {
invokeOnDelegate = delegate != closure && (delegate instanceof GroovyObject);
}
break;
Source: src/main/java/org/codehaus/groovy/runtime/metaclass/ClosureMetaClass.java#L275-L284
The invokeOnDelegate boolean flag verifies if the delegate object extends GroovyObject (the default parent class for all Groovy classes.) When you execute your code with Groovy classes, this flag is set to true and the anything method from the delegate object gets invoked. In the case of non-Groovy classes, MethodMissingException is thrown.
You can debug this behavior by setting the breakpoint in AbstractCallSite.callCurrent(GroovyObject receiver) line 160. You will see that in all cases the method anything is not found in the closure, but in the first two cases invokeOnDelegate is evaluated to true, and the invokeMethod on delegate object is executed. It does not happen in the third case, because ArrayList is not an instance of GroovyObject.

How can a mock's class not equal its java class in Kotlin?

(activity as HomeActivity).javaClass == HomeActivity::class.java
Returns false. Why? Note, activity is mocked with the following function
fun set(activity: KClass<out Activity>) {
this.activity = Mockito.mock(activity.java)
}
You probably want to use:
if(activity is HomeActivity) instead (activity as HomeActivity).javaClass == HomeActivity::class.java
The reason is Mockito.mock(HomeActivity.java) will dynamically create a class which implements HomeActivity using SomeFooMockitoImpl.class which gets HomeActivity.class as parameter to create that mocked instance.
You can check in runtime mock object will be something like:
HomeActivity$$EnhancerByMockitoWithCGLIB$$b8254f54
and its actual class name by:
activity.javaClass.simpleName (should be SomeFooMockitoImpl)

Mocking static class in Mockito

I have something like the following:
public class Foo {
public static String getValue(String key) {
return key + "_" + System.currentTimeMillis();
}
}
Now I need to have a test case for it and here is how I attempted:
#Test
public void testFoo() {
PowerMockito.mockStatic(Foo.class);
PowerMockito.when(Foo.getValue("123")).thenReturn("abcd");
PowerMockito.verifyStatic();
}
When I run the test case, I get this:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
at org.powermock.api.mockito.PowerMockito.when(PowerMockito.java:495)
Am I doing anything wrong?
Please advise.
Can you confirm that you've added a #PrepareForTest(Foo.class) annotation onto your test class as listed on the PowerMock site, and that you're using the PowerMockRunner JUnit4 runner?
Static methods are invoked with static dispatch, not dynamic dispatch using Java's normal polymorphism and method overrides. To replace the implementation, PowerMock needs to load a replacement class before the test starts running, and the runner and annotation make that happen.

Midlet is not abstract and does not override abstract method focusLost(com.sun.lwuit.Component)

I have a LWUIT class which has a List, the list itself contains a Label as an item.
My idea simply to make an action for the list when I focus on the label.
I get the following error, when compiling the class:
anonymous Midlet$2 is not abstract and does not override abstract
method focusLost(com.sun.lwuit.Component) in
com.sun.lwuit.events.FocusListener
String s = ("Focus me");
final com.sun.lwuit.Form f = new com.sun.lwuit.Form();
final com.sun.lwuit.List D = new com.sun.lwuit.List();
final com.sun.lwuit.Label l = new com.sun.lwuit.Label(s);
D.addItem(l);
f.addComponent(D);
D.addFocusListener(new com.sun.lwuit.events.FocusListener () {
public void focusGained(com.sun.lwuit.Label l)
{
}
public void focusLost(com.sun.lwuit.Label l)
{
}
});
All details of what is wrong with your code are in the error message, you just need to carefully read it. Look,
word anonymous and sign $ in Midlet$2 tell you something is wrong in the anonymous class.
In your code snippet, there's only one such class: new com.sun.lwuit.events.FocusListener
does not override abstract method focusLost(com.sun.lwuit.Component) means your anonymous class misses a definition of a method with such a signature (signature is method name and type of parameters)
Look closer in the methods you defined in that anonymous class, is there a method compiler is complaining about?
At the first glance, you may think it's there, there's a method called focusLost - but (!) you need to remember that signature is not only method name, but also parameters type - and (!) if you look closer, you'll find out that parameter type is not that is said to be required in error message.
Your anonymous class has method focusLost(com.sun.lwuit.Label) but error message says there should be method with different signature (different parameter type) - focusLost(com.sun.lwuit.Component).
To fix this compilation error, add to the anonymous class new com.sun.lwuit.events.FocusListener a method with required signature: focusLost(com.sun.lwuit.Component).

Resources