Skip to main content
Inspiring
September 8, 2018
Answered

onApplicationStart display

  • September 8, 2018
  • 2 replies
  • 1804 views

Hi all. I am using orms, so my application takes a while to start (about 3 minutes)

I would love to be able to display something to the user - e.g., Starting xxx, please wait...

When I add a <cfoutput> as the first line of onApplicationStart (output=true), nothing displays (index.cfm is executed).

If I add <cfflush> after the <cfoutput>, message displays (index.cfm is not executed!)

Any ideas?

This topic has been closed for replies.
Correct answer martiehen2

BKBKCharlie Arehart
thank you so much for your insight and thoughtful suggestions. I tried them, along with several other variations, and had exactly the same problems as my original post - with a new addition.

  • Either nothing displays (depending on cfflush interval)
  • Displays, but stops execution (never goes to index.cfm)
  • Or a new one - I get an error message that I'm attempting to execute a cfflush when I can't (e.g. in a cfthread)

Apparently, cold fusion isn't going to allow you to display anything until onApplicationStart is completed, although I can't even begin to understand why that is.

Rather than beat my head against the wall with CF, I decided to try something entirely different - index.html to the rescue.

  • Renamed my index.cfm to start.cfm (to avoid default page issues for the website)
  • Created index.html

index.html

<!DOCTYPE html>

<html>

<head>
</head>
<body>

<h2>Application is loading, just a moment please</h2>

<script type="text/javascript" language="javascript">

window.location = "start.cfm";

</script>

</body>

</html>


Works perfectly. HTML is displayed, and sits there until CF gets around to fulfilling the request for start.cfm

Now that the issue is solved, I can even get fancy with an animated loading image, woo hoo!

I've been working with CF since version 5, now running CF 2016.
I too was totally amazed that I couldn't find an answer to displaying a start message without asking a question, especially with the introduction of orm in CF9, which impacts onApplicationStart execution time.

FYI, I've got a real ball buster of an Application.cfc, supporting 6 separate, yet interconnected sites. I got sick of having to change the same things in all 6, so I parameterized.
Application.cfc extends ApplicationMaster.cfc, and ApplicationMaster.cfc extends ApplicationVars.cfc

Application.cfc is the a series of this.xxx = ..., same template, different values commented/uncommented for each site, and executes an appInit in ApplicationMaster, and has the onError function
ApplicationMaster.cfc and ApplicationVars.cfc are exactly the same code for all sites, making liberal use of switch statements

Perhaps something to do with my complex structure is what caused your suggestions to not work properly?

Seems like the simplest solution evaded us while we were drinking CF kool-aid.

Still curious as to why CF blocks output until onApplicationStart is finished.

Perhaps I'll play around a bit more and see if I can figure out a work-around with CF

PS - Wouldn't it be nice if there was a place to put a template in CFAdmin for this, and have CF display the template when it's starting?

2 replies

martiehen2AuthorCorrect answer
Inspiring
September 12, 2018

BKBKCharlie Arehart
thank you so much for your insight and thoughtful suggestions. I tried them, along with several other variations, and had exactly the same problems as my original post - with a new addition.

  • Either nothing displays (depending on cfflush interval)
  • Displays, but stops execution (never goes to index.cfm)
  • Or a new one - I get an error message that I'm attempting to execute a cfflush when I can't (e.g. in a cfthread)

Apparently, cold fusion isn't going to allow you to display anything until onApplicationStart is completed, although I can't even begin to understand why that is.

Rather than beat my head against the wall with CF, I decided to try something entirely different - index.html to the rescue.

  • Renamed my index.cfm to start.cfm (to avoid default page issues for the website)
  • Created index.html

index.html

<!DOCTYPE html>

<html>

<head>
</head>
<body>

<h2>Application is loading, just a moment please</h2>

<script type="text/javascript" language="javascript">

window.location = "start.cfm";

</script>

</body>

</html>


Works perfectly. HTML is displayed, and sits there until CF gets around to fulfilling the request for start.cfm

Now that the issue is solved, I can even get fancy with an animated loading image, woo hoo!

I've been working with CF since version 5, now running CF 2016.
I too was totally amazed that I couldn't find an answer to displaying a start message without asking a question, especially with the introduction of orm in CF9, which impacts onApplicationStart execution time.

FYI, I've got a real ball buster of an Application.cfc, supporting 6 separate, yet interconnected sites. I got sick of having to change the same things in all 6, so I parameterized.
Application.cfc extends ApplicationMaster.cfc, and ApplicationMaster.cfc extends ApplicationVars.cfc

Application.cfc is the a series of this.xxx = ..., same template, different values commented/uncommented for each site, and executes an appInit in ApplicationMaster, and has the onError function
ApplicationMaster.cfc and ApplicationVars.cfc are exactly the same code for all sites, making liberal use of switch statements

Perhaps something to do with my complex structure is what caused your suggestions to not work properly?

Seems like the simplest solution evaded us while we were drinking CF kool-aid.

Still curious as to why CF blocks output until onApplicationStart is finished.

Perhaps I'll play around a bit more and see if I can figure out a work-around with CF

PS - Wouldn't it be nice if there was a place to put a template in CFAdmin for this, and have CF display the template when it's starting?

Charlie Arehart
Community Expert
Community Expert
September 14, 2018

Martiehen2, glad you found some workaround. But you wonder why “CF blocks output until onApplicationStart is finished.” Again, it does not. Instead, it single-threads execution of the onapplicationstart method, until the method completes.

What you see as it “blocking output” is instead just CF blocking the request you are running while that finishes--whether yours is the request that triggers the onapplicationstart (implicitly, by running as the first request when the app has not been started), or whether yours is a request trying to run while some other one has triggered that.

And again, this is why I offered in my code a way to get CF to NOT hangup during processing of onapplicationstart.

/charlie

/Charlie (troubleshooter, carehart. org)
BKBK
Community Expert
Community Expert
September 9, 2018

Index.cfm and other CFM pages are triggered by onRequestStart, not by onApplicationStart. But onRequestStart fires much later. That explains what you observe.

I have a suggestion you may like to test. It consists of 3 files: Application.cfc, waitOnStart.cfm and index.cfm,

Points to note:

  • I have assumed you have a recent version of ColdFusion.
  • Make wait-message user-friendly by calling the application by name. In this case, EmployeeAdmin.
  • When you estimate the value of the flush interval, take one character to be worth 1 byte, including space, carriage-return and characters in HTML tags.

Application.cfc

<cfcomponent>

    <cfscript>

        this.name = "EmployeeAdmin";

        this.applicationTimeout = createTimespan(1,0,0,0);

        this.sessionManagement = "true";

        this.sessionTimeout = createTimeSpan(0,0,20,0);

    </cfscript>

    <cffunction name="onApplicationStart" returntype="boolean">

        <!--- Displays "wait" message to user --->

        <cfinclude template="waitOnStart.cfm" runonce="true">

        <cfset application.isInitiated=true>

      

        <!---

        The business code here takes several minutes.

        Simulate by a sleep of 60 seconds, for example.

        --->

        <cfset sleep(60000)>

      

        <cfreturn true>

    </cffunction>

    <cffunction name="onRequestStart">

        <cfargument name = "targetPage" type="String" required="true">

        <!--- Displaying the wait message is relevant only when application.isInitiated is true. That is, only on application start. --->

        <cfif isDefined("application.isInitiated") and application.isInitiated>

        <script type="text/javascript">

         document.getElementById('loadApplication').style.display='none';

        </script>

      

        <cfset application.isInitiated=false>

        </cfif>

      

        <cfreturn true>

    </cffunction>

</cfcomponent>

waitOnStart.cfm

<cfflush interval="90">

<p id="loadApplication">

EmployeeAdmin is starting. <br>

Please wait a few minutes.  

</p>

index.cfm

Test page. The time is: <cfoutput>#now()#</cfoutput>

Charlie Arehart
Community Expert
Community Expert
September 9, 2018

I think solving this is going to be more complicated than that. The issue is that I'm pretty sure CF will single-thread all requests (to a given app on its first execution) waiting for the onapplicationstart to finish. So no code will run in onrequestart until then.

This is an interesting challenge, and one I'm surprised to not have seen being asked about much before.

I'd propose a variation on this code: do the actual startup of the app (the real meat in onapplicationstart) in a cfthread that is allowed to run asynchronously. And wrap the execution of that code in a test that only allows it to run once, when being initiated this way.

Then that "first" request should be allowed to "end" by showing a message saying that the app is being started, and that they should wait and try again. The same should be shown for all other requests, until the app IS loaded. After it is, then any requests should be allowed to run as normal.

To be clear, the reason for using cfthread above is so that this first requester IS allowed to end quickly reporting that the app is still loading. More important, it allows the onapplicationstart method to finish for that first request (and not hold up it or others).

Of course, the code in the cfthread would end by setting an application variable tracking that the app IS now loaded, which would be detected on subsequent requests.

As for how the code in the cfthread should "only run once", that gets tricky in that it should handle both when this is the very first initiation of the app at server startup, as well as later if something triggers another app reload. At that point it SHOULD be allowed to run again of course, though--as before--only for the first request running at that time.

Hope that may be helpful. I would love to hear if anyone either finds another resource expanding on this or if anyone takes this ball and runs with it.

Finally, someone may want to point out that there are other ways to "warm up" the app by calling it before the first user would. There are various solutions for that,  such as the onserverstart cfc feature of CF. Note that won't help if the app is released mid-day. Same if someone might propose a nightly scheduled task.

Also note that IIS 8 and above offers an optional app warmup feature that can help here. (It's not an IIS feature installed by default with IIS.)

/Charlie (troubleshooter, carehart. org)
BKBK
Community Expert
Community Expert
September 10, 2018

https://forums.adobe.com/people/Charlie+Arehart  wrote

I think solving this is going to be more complicated than that. The issue is that I'm pretty sure CF will single-thread all requests (to a given app on its first execution) waiting for the onapplicationstart to finish. So no code will run in onrequestart until then.

Thanks for your remark, Charlie Arehart​. In fact, the code in the above example takes account of this, It shows the user a message while onApplicationStart is still running. That is, before we get to onRequestStart.