Reputation: 24831
I don't know if this is a bug or a feature, but it's definitely unintuitive to people from a Java background to track the reason of exception.
Groovy allows variables to be referred to even if the variable is not defined. For example consider the below class:
class B {
def infos;
public B(String param)
{
infos = param
}
public getInfo()
{
return info;
}
}
If you noticed, inside getInfo()
, I am returning info
which is never defined. However, Eclipse does not give a warning. So I continue on writing following:
class A
{
static main(def args)
{
B bObj = new B("Mahesh")
println "Hello groovy"
println bObj.getInfo()
println "Hello groovy"
}
}
Now this gives StackOverflowError
with a huge stack trace:
Exception in thread "main" java.lang.StackOverflowError
at java.lang.Exception.<init>(Exception.java:102)
at java.lang.ReflectiveOperationException.<init>(ReflectiveOperationException.java:89)
at java.lang.reflect.InvocationTargetException.<init>(InvocationTargetException.java:72)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at groovy.lang.MetaClassImpl$GetBeanMethodMetaProperty.getProperty(MetaClassImpl.java:3493)
at org.codehaus.groovy.runtime.callsite.GetEffectivePogoPropertySite.callGroovyObjectGetProperty(GetEffectivePogoPropertySite.java:67)
--> at packages.B.getInfo(ThreadDumpsExp.groovy:169) <--
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at groovy.lang.MetaClassImpl$GetBeanMethodMetaProperty.getProperty(MetaClassImpl.java:3493)
at org.codehaus.groovy.runtime.callsite.GetEffectivePogoPropertySite.callGroovyObjectGetProperty(GetEffectivePogoPropertySite.java:67)
:
:
The stack trace here was ok since somewhere down in the stack trace it pointed to this specific line which I highlighted in the above stack trace with arrows. I was expecting this line in the stack trace, that's why I was able to quickly track it down. The issue arose when today I came across same issue in my project. The stack trace was equally huge. I had no idea where it is actually going wrong so I can not make a guess about which line might actually be faulting. Worst it was stopping in Groovy's source during debugging. I had to repeatedly put breakpoints at different places to actually halt the execution at them. After some time I found the line where the debugger actually stopped inside my code. From there I stepped through my whole code to find the line which was causing issue. That line was a simple getter which was returning te wrong thing.
Now I know I should be more conscious while writing code and should not make such mistakes of returning a non-existent variable from a getter. But is there any way to make it not do what it did above?
Edit
Also after adding @TypeChecked
, below error occurs. It was working properly earlier.
Upvotes: 4
Views: 1419
Reputation: 19692
When you add a getter for a property, regardless of whether the property exists, you need to reference the property with the .@
operator. This is the direct field access operator, which skips any getter and goes straight to the property. If you don't use the operator the same getter will be invoked over and over until you get a StackOverflowError
.
For example:
def getInfo() {
return this.@info
}
See Section 6.2 Direct field access operator in the Groovy operator docs for a little more.
Upvotes: 8
Reputation: 487
The problem lies in the signature of the getInfo-Method which implies that this is a getter. When you call a property of a class (here with "return info") than implicitly groovy uses the getter getInfo. This creates a endless loop which results in the StackOverflowError (because info calls getInfo, getInfo calls info, calls getInfo ...). If you use another not-existing property in here (i.e. return foo) you receive the expected MissingPropertyException. To avoid this behavior you should not define getter-Methods with names matching to not-existing properties.
Upvotes: 2