On 11.10.2017 19:11, Basurita wrote:
Hi, I've been away from the Groovy world for some years.
As of recently, I've been trying to add some behavior to Groovy scripts 
embedded in a large Java codebase.
A few things that I "half-remembered" striked me as odd.
In this mail I want to ask about why Groovy does not honor certain methods for 
POJOs

My questions:
   * Why does Groovy NOT honor get/setProperty for pojos?
   * Why does it honor propertyMissing?

I'm sure there must be good/historical reasons for this incongruency, but I 
haven't been able to google a good answer.
And I don't think the answer will be "oh! we've never thought of that!" :-)
If it were up to me, I would honor both or none...

And I'm not looking for "solutions" that add those methods through a metaClass 
blah blah
I just would like a good rationale behind the way Groovy "naturally" handles 
properties for POJOs

if we talk about foo.bar in Groovy then the semantics are the following (simplified):

* Iff foo is a GroovyObject, call foo.getProperty("bar"). The default implementation for this will use a property accessor to access the property. This accessor is normally the getter method.
* Iff foo is no GroovyObject we go directly to the meta class.

In the meta class the process is roughly the following:

step 1: Iff there is a getter getBar use getBar unless the property has been overwritten by meta programming
step 2: ... do some other things
step 3: Iff step 1 and 2 do not apply and foo defines a propertyMissing(String) method, use that to get the property

The effect is the following:

class Foo {
  def bar = 1
  def getProperty(String name) {2}
}
assert new Foo().bar == 2

Even though we have a getBar method,we are not using it, we are using the getProperty method. getProperty is called in the beginning of the dispatch.

class Foo {
  def bar = 1
  def propertyMissing(String name) {2}
}
assert new Foo().bar == 1

See how we here call the getBar method, even though you defined a propertyMissing?

class Foo {
  def propertyMissing(String name) {2}
}
assert new Foo().bar == 2

class Foo {
  def getProperty(String name) {2}
}
assert new Foo().bar == 2

Only if the getter is missing the two seem to have the same semantics. But even then it is not the case. propertyMissing can be added by meta programming. For getProperty it must be a static method, which is then called in Java fashion.

Can you see the difference now?

If you want a historic view on this... getProperty was there first and I think back then the call to getProperty was actually hardcoded and directly written into the file. This changed early on with ScriptBytecodeAdapter, which catched more cases (foo is null for example), but the call is still a java call. And the original idea was I think if getProperty is there (it must be if it implements GroovyObjects, which all Groovy classes do) you can have the same semantics if you make the call from Java or from Groovy. propertyMissing was added with the advent of Grails, that did need a fallback method. This is not part of an interface, there is no Java based contract for this and for Java to call directly, thus we made this much more flexible. And I think in the future GroovyObject will (together with set/getProperty and get/setMetaclass) go away... at least the methods in there will.

[...]
For reference, I created a POJO and added the following:

you added the POJO and marked how you want it to behave ;) That is important, because it is, the program will fail to pass the asserts. Why should be clear now I hope.
[...]

bye Jochen

Reply via email to