Application scoped variables are getting refreshed for each requests

202 Views Asked by At

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 enter image description here

Again refreshing the page also giving the same output enter image description here

Not sure why the Application scoped variables are losing its persistence.

the following is the expected output..

enter image description here

Any idea of Why the application variables are lost and getting refreshed on each and every request ?

1

There are 1 best solutions below

1
On

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.