Copy link to clipboard
Copied
I've recently upgraded a server to CF2023, which has many legacy apps that currently rely on implicit variable scoping. I've temporarily added the Dcoldfusion.searchimplicitscopes=true Java flag for the server, and was hoping to work through the individual apps and test them by overriding that in application.cfc with this.searchImplicitScopes = false.
Thanks, Charlie, for the detailed response. In my case, this.searchImplicitScopes was being set in the right place before the functions, but your link to the getApplicationMetadata() function got me to the answer. The function result was an empty struct because this.applicationTimeout was set to 0, forcing the application to update for debug/testing (but apparently also clearing any settings before they could take effect). After setting a non-zero value for applicationTimeout, the searchImplicit
...Copy link to clipboard
Copied
I Start with a minor point. There is a typing error in the flag you wrote, "Dcoldfusion.searchimplicitscopes=true". It should start with a minus sign, thus
-Dcoldfusion.searchimplicitscopes=true
Not that that is relevant to your question. As ColdFusion would not even have started without the minus sign.
To answer your question, yes, the searchImplicitScopes setting in Application.cfc overrides the one in jvm.config. The following test will show that:
<cfset url.Testvar=1>
<cfoutput>
TestVar: #TestVar# <br>
Script_Name: #script_name#
</cfoutput>
TestVar: 1
Script_Name: /path/to/the/cfm/file
6. Relaunch the CFM file;
You will get the error message "Variable TESTVAR is undefined.".
This confirms that the Application.cfc setting has overriden the server-wide setting.
Copy link to clipboard
Copied
Nate, you ABSOLUTELY can override the jvm arg at the app level. I've confirmed it. But I have a guess at why your attempt to override it in your application.cfc is not working. At least this could happen to others.
Are you putting the this.searchimplicscopes=false inside your onapplicationstart, or perhaps onrequest or onrequeststart? If so, that's the problem. Instead, put the setting OUTSIDE those methods, which as some may know has been referred to traditionally in CFML as the "pseudo-constructor" of a CFC.
You can prove this yourself by dumping the getApplicationMetadata() function, which shows what is or is NOT set for such settings as can be set at the application level (and so yes, this issue applies to ANY such application settings).
You can even see this indicated in the docs talking about using application.cfc, though they don't make a point of stressing it. They just show DOING it. As for the docs on the various application settings you can set, those do at least say at the top, "You set the values of these variables in the CFC initialization code, before you define the CFC methods."
Sadly, neither of those doc pages propose the idea of using getApplicationMetadata(), which is the best way to confirm where things stand regarding such settings. And I'll note that if instead one were to dump the THIS scope, you WILL see the change you'd made via the "this." scope even within those methods. But the problem is that that is NOT going to matter, if you don't see it reflected in the dump of getApplicationMetadata().
FWIW, you would not be the first to experience that "changing settings in application.cfc is not working". Of course, those who use application.cfm don't experience this, as they just set the settings on cfapplication instead, which is a more straightforward runtime directive.
Here also is some code you can use to "play with" things:
component {
// this code demonstrates how to correctly and incorrectly) set application-level settings like searchimplicitscopes in application.cfc
// it presumes that the default setting in CF is set to true, and that one wants to set it false for this given app (as discussed in this forum thread)
// to test some changes, you'll want to re-initalize the app.
// while you could call applicationstop(), you could also just change the value of this.name to create a "new" app
this.name="test";
// this line sets the setting correctly, as it's outside any method
this.searchimplicitscopes=false;
writedump(var=this,label="this, in pseudo-constructor")
writedump(var=getApplicationMetadata(),label="getappmetadata, in pseudo-constructor");
function onapplicationstart() {
// this line will NOT set the setting to true, because it's inside onapplicationstart
this.searchimplicitscopes=true;
writedump(var=getApplicationMetadata(),label="getappmetadata, in onapplicationstart");
writedump(var=this,label="this, in onapplicationstart");
}
function onrequeststart() {
// this line will also NOT change the setting. Note you can even set it to an incorrect value without any error,
// which would fail if done on the correct line above (with 'cannot convert the value "xx" to a boolean')
this.searchimplicitscopes="xyz";
writedump(var=getApplicationMetadata(),label="getappmetadata, in onrequeststart");
writedump(var=this,label="this, in onrequeststart");
}
}
You can also add a dump of the scope in a cfm page (such as even a a new test.cfm you may create) in the folder controlled by this application.cfc:
<cfdump var="#getapplicationmetadata()#" label="getappmetadata, in #cgi.script_name#">
Finally, if you may want some code to detect and show if the new JVM arg for searchimplicistscopes is set, this will do it:
// code to detect and show if JVM arg for coldfusion.searchimplicitscopes is set
writeoutput("jvm arg -Dcoldfusion.searchimplicitscopes ");
if (structkeyexists(server.system.properties,"coldfusion.searchimplicitscopes")) {
writeoutput("set to " & server.system.properties["coldfusion.searchimplicitscopes"] & "<br>");
} else {
writeoutput("is not set <br>");
}
I've been meaning to do a blog post on this matter (of how one might mistakenly set the setting), and in answering you here it has helped me gather the thoughts. I'l look forward to hearing what you or others may say, in case there's anything I'm missing.
Copy link to clipboard
Copied
Thanks, Charlie, for the detailed response. In my case, this.searchImplicitScopes was being set in the right place before the functions, but your link to the getApplicationMetadata() function got me to the answer. The function result was an empty struct because this.applicationTimeout was set to 0, forcing the application to update for debug/testing (but apparently also clearing any settings before they could take effect). After setting a non-zero value for applicationTimeout, the searchImplicitScopes setting worked as expected.
Copy link to clipboard
Copied
Wow, there you go and glad that helped. That's why I LOVE showing ways to DIAGNOSE problems, while often we try to guess at causes/solutions.
And TBH I don't think I've ever heard of one setting the app timeout to zero, but it just goes to show that the strangest things can happen and explain a knotty problem. 🙂
And perhaps the rest of what I shared will yet help someone else, now or in the future, in their finding some setting "fails to take effect".
I'll mark your reply as the "answer" for this thread. (Though you could have done it yourself, you might not have thought of it).
Copy link to clipboard
Copied
@NateBaldwin , thanks for sharing that. I am surprised that you could successfully launch a CFM with applicationTimeout set to 0. I expected ColdFusion to then give an exception.
So I did a test. As a result, I discovered an inconsistency in ColdFusion. It is this inconsistency that resulted in the issue that you observed.
The steps of the test:
<!--- Applicstion.cfc used. The explicit presence of cookie settings might be relevant to the bug. --->
<cfcomponent>
<cfscript>
this.name = "MyTestApp";
this.applicationTimeout = "#createTimespan(0,0,0,0)#";
this.loginStorage = "session";
this.sessionManagement = "true";
this.sessionTimeout = "#createTimeSpan(0,0,20,0)#";
this.setClientCookies = "true";
this.setDomainCookies = "false";
this.scriptProtect = "all";
this.enableNullSupport = false;
</cfscript>
<cffunction name="onApplicationStart" returntype="boolean">
<cfreturn true>
</cffunction>
<cffunction name="onRequestStart" returntype="boolean">
<cfargument name = "targetPage" type="String" required="true">
<cfreturn true>
</cffunction>
</cfcomponent>