Reputation: 1124
We've migrated a ColdFusion application from ColdFusion 10 to ColdFusion 2016. After Migration, Application variables are not staying in its scope, it is refreshing on each and every request.
Consider the following example,
Application.cfm
<cfsetting enablecfoutputonly="true" />
<CFAPPLICATION NAME="Test App"
SETCLIENTCOOKIES="YES"
CLIENTMANAGEMENT="YES"
SESSIONMANAGEMENT="YES"
SESSIONTIMEOUT="#CREATETIMESPAN(0,8,0,0)#"
APPLICATIONTIMEOUT="#CREATETIMESPAN(1,0,0,0)#">
<cfdump var="#Application#" label="app">
<CFLOCK SCOPE="APPLICATION" TYPE="EXCLUSIVE" TIMEOUT="10">
<CFSET Application.Email = "[email protected]">
<CFSET Application.DataSource="test">
</cflock>
Test.cfm
<CFLOCK SCOPE="APPLICATION" TYPE="READONLY" TIMEOUT="10">
<cfset Application.one = 1>
<cfset Application.two = 2>
<cfset Application.three = 3>
</cflock>
OnRequestEnd.cfm
<cfsetting showdebugoutput="false" />
<cfdump var="#Application#" label="onRequestEnd">
So if we request /test.cfm
it'll throw the following output
Again refreshing the page also giving the same output
Not sure why the Application scoped variables are losing its persistence.
the following is the expected output..
Any idea of Why the application variables are lost and getting refreshed on each and every request ?
Upvotes: 4
Views: 226
Reputation: 14859
I haven't tested this code, but what you're seeing is the procedural order of operation performed by Application.cfm
. You're essentially redefining the application on every request, which is why on the name exists in your initial dump and the rest exist on the dump in onRequestEnd
.
If you update your code to use Application.cfc
, you can ditch the cflock
code, better organize your "triggers" and define your application variables once, when needed, using onApplicationStart
.
<cfcomponent>
<cfset this.name = "Test App">
<cfset this.SETCLIENTCOOKIES="YES">
<cfset this.CLIENTMANAGEMENT="YES">
<cfset this.SESSIONMANAGEMENT="YES">
<cfset this.SESSIONTIMEOUT="#CREATETIMESPAN(0,8,0,0)#">
<cfset this.APPLICATIONTIMEOUT="#CREATETIMESPAN(1,0,0,0)#">
<cfsetting enablecfoutputonly="true" />
<cffunction name="onApplicationStart" access="public" returnType="void" output="false">
<cfset application.Email = "[email protected]">
<cfset application.DataSource="test">
</cffunction>
<cffunction name="onRequestStart" access="public" returntype="boolean" output="false">
<cfset application.one = 1>
<cfset application.two = 2>
<cfset application.three = 3>
<cfreturn true>
</cffunction>
<cffunction name="onRequestEnd" access="public" returntype="boolean" output="false">
<cfsetting showdebugoutput="false" />
<cfdump var="#application#" label="onRequestEnd">
<cfreturn true>
</cffunction>
</cfcomponent>
This should define email
and datasource
in the application scope one time, when the app first loads. The variables one
, two
and three
will be created at the start of each request, but you can add a check to set them only if they don't already exist.
You can then use child Application.cfc
files to help modularize your application using sub-folders and sub-application specific variables. They'll still exist in the scope of the larger application, but you'll be able to manage them from a location specific to a sub-app this way.
Upvotes: 3