Issue with implicit accessors
Our development team recently discovered that we are getting multiple errors when using implicit get accessor (person.firstName) instead of generated get accessor (person.getFirstName()). Here are instructions of how to reproduce the error:
- Create a new ColdFusion application with the following files:
Application.cfc:
component {
this.invokeImplicitAccessor = true;
}
Person.cfc:
component accessors=true {
property firstName;
}
index.cfm:
local.person = new Person();
local.person.firstName = "Zachary";
for( local.i = 0; local.i lt 1000; local.i++ ) {
local.j = local.person.firstName;
}
index2.cfm:
local.person = new Person();
local.person.firstName = "Zachary";
for( local.i = 0; local.i lt 1000; local.i++ ) {
local.j = local.person.getFirstName();
}
Test the index.cfm with JMeter, use 2000 threads, 10s Ram-Up Period and Loop count 1 (test plan: https://pastebin.com/nBtpL4zP)
In our tests the page always fails with the same error message:
Element PERSON.FIRSTNAME is undefined in LOCAL.
The error % we are getting with the above settings usually falls somewhere between 8 to 10 %, meaning that 160 to 200 requests out of >2000 requests fails.
When index2.cfm gets tested with the same settings, we don't get any errors
Here are some details about the test environment:
OS: Windows Server 2016 Standard ColdFusion: Adobe ColdFusion 2018 Release JMeter 5.0 (https://jmeter.apache.org/download_jmeter.cgi)
Does anyone have any idea why this is happening? Is there some ColdFusion settings we could tweak? The above example application is very minimal, and we are not doing anything special, so I don't see any reasons why implicit accessors should fail, especially when generated accessors seems to pass the same test without any issues.
We appreciate any help or suggestions of what to try to get the implicit accessors working.
EDIT: Fixed index2.cfm to use get() method instead of implicit accessor.
EDIT2: Full error message/page: https://pastebin.com/budqiV1m
EDIT3: I have created a bug report for this: https://tracker.adobe.com/#/view/CF-4203997
The accessors are functions. If you have
The correct way to use implicit accessors is this.getFoo() or just getFoo() (inside the component) or myComponent.getFoo() outside the component.
this.getFoo is a pointer to the getter and not the getter itself. In your example, local.j = local.person.firstName; is setting j to a pointer to the getter and not the value of the property; it should be person.getFirstName() if indeed you want to use the implicit accessor.
It has not been the case for many years now that explicit getters or setters are faster (on either ACF or Lucee). You can, of course, still write them if you need them and they'll overwrite the implicit functions.
While this example is from Adobe's ORM docs, it better illustrates how implicit accessors should be used:
https://helpx.adobe.com/coldfusion/developing-applications/coldfusion-orm/working-with-objects/generated-accessors.html
Here is a more complete explanation -- even though it's for Lucee, it works this way in ACF as well:
https://rorylaitila.gitbooks.io/lucee/content/properties.html
Finally, while not relevant to the problem, the local scope is a function scope and on a .cfm page just the variables scope in disguise. You can drop local from all of that code as it's somewhat misleading -- unless you're inside a function definition inside your .cfm page (which you shouldn't be) you're in variables scope territory and if you want to be explicit about it, variables is what you should use.