14 Replies Latest reply on Jun 16, 2007 12:00 PM by Chuck1411

    Application.cfc(s) and sharing values

    Matt Binz
      I'm attempting to use multiple Application.cfc files as part of a "suite" running under 7. Essentially one big app that runs other smaller apps within it.

      My original thought was to use multiple Application.cfc files (one in each sub-app directory as well as one 'parent')...goal being to share some constants and variables (i.e. datasource, company name, application version information, etc) but have different onRequestStart/End functions for each sub-app. Am I dreaming in thinking there is a parent-child relationship when using multiple Application.cfc files and the sharing of values could just happen? Specifically, variables with APPLICATION.xxxxx scope in the highest application controller is screaming an error when executed in a sub-app.
        • 1. Re: Application.cfc(s) and sharing values
          Dan Bracuk Level 5
          server variables are simpler.
          • 2. Re: Application.cfc(s) and sharing values
            Level 7
            Yes you are dreaming that they will share automatically. You have to
            specifically tell the child cfc|objects to inherit the parent cfc using
            the extends parameter in the <cfcomponent ...> tag.

            Then you will get the behavior for which you are looking.
            • 3. Application.cfc(s) and sharing values
              iKnowKungFoo
              /Application.cfc
              /calendar/Application.cfc [ extends="Application" ]
              /contacts/Application.cfc [ extends="Application" ]

              In the root Application.cfc, any application variables you define in onApplicationStart() will be created when you hit any of the sub-applications before the main application has started.

              If the root Application.cfc uses onRequestStart() to define global request variables and you want to define request variables specific to the calendar application, in /calendar/Application.cfc, inside onRequestStart() you first have to call super.onRequestStart() to run that function from the root Application.cfc, then you can write any code specific to the sub-application.

              • 4. Re: Application.cfc(s) and sharing values
                Chuck1411 Level 1
                Hi, when I try to use this, I get the error message, component tracker.application cannot extend itself. Do I have to give a relative path to the extends="application" as something like extends="../application"?
                • 5. Re: Application.cfc(s) and sharing values
                  Chuck1411 Level 1
                  apparently you can use extends="/.Application" as from this persons blog...
                  check the comment by Ben Dolman.

                  http://corfield.org/blog/index.cfm/do/blog.entry/entry/Extending_Your_Root_Applicationcfc# postcomment

                  I'm testing this now.
                  • 6. Re: Application.cfc(s) and sharing values
                    Chuck1411 Level 1
                    Having problems with the SESSION scope persisting across applications. The APPLICATION scope is there no problem - apparently.

                    What is apparently happening is that there are different Session scopes for each application.cfc, even though they show the same data in some respects like cfid cftoken.

                    I have only gotten it to work if the apps have the same this.name value, but then that isn't inheritance, I think that is the same application name sharing.
                    • 7. Re: Application.cfc(s) and sharing values
                      iKnowKungFoo Level 1
                      Make sure you only name the application under the root Application.cfc. Even though the sub-applications have their own Application.cfc files, it's really all one big application with different "modules".
                      • 8. Re: Application.cfc(s) and sharing values
                        Chuck1411 Level 1
                        Thanks Cf_menace, that clears things up.
                        • 9. Re: Application.cfc(s) and sharing values
                          Chuck1411 Level 1
                          When I Log in to my main application, and then use a link from my menu to the module, it isn't finding the application scope right away, or it isn't instantiating my objects quickly.

                          IE in the onRequestStart I do a
                          REQUEST.component = APPLICATION.component (because it wasn't finding it in APPLICATION fast enough, and I did this because it helped a bit, but still I get errors that the component doesn't exist. Even though it is created in the onApplicationStart as
                          APPLICATION.component = createobject(...)

                          any clues what is going on? I have to demonstrate this app soon, I may end up having to move all the module stuff into the main application.cfc and differentiate what is the module vs what is other modules with switch statements, making for ugly code.

                          thanks for any help
                          • 10. Re: Application.cfc(s) and sharing values
                            Chuck1411 Level 1
                            Ok, I think i have it figured as to why I'm having this behavior. Basically requests are handled asynchronously, so the onApplicationStart is still processing the createobject, and the onRequesStart is trying to use the component that hasn't finished loading. That is why sometimes it works, and sometimes not, and if not, its only a matter of seconds before it does work.
                            so that problem is a locking issue, but I have another question related to inheritence in application.cfc

                            Does the module onApplicationStart have to call Super.onApplicationStart() if the application was first encountered in the main? I guess my instinct is telling me to check in the main app to see if the variables are already created, and if so, just skip the code, so I don't re instantiate a ton of objects.
                            • 11. Re: Application.cfc(s) and sharing values
                              Chuck1411 Level 1
                              Ok, and apparently I was wrong on my assumption. The OnRequestStart of the extended application.cfc is running before its OnApplicationStart method. Am I wrong or this a bug?

                              Because the lock on the OnApplicationStart method being exclusive should lock a readonly of scope application first, but it isn't. So my reasoning is that the OnApplicationStart method isn't being called first in the module. It eventually does get loaded (before I added the locks), so I reason it eventually does get called.
                              • 12. Re: Application.cfc(s) and sharing values
                                Chuck1411 Level 1
                                I believe this a bug, but here is my answer...
                                Code:
                                <cffunction name="onRequestStart" returntype="boolean" output="yes">
                                <cfargument name="targetPage" type="String" required="true" />
                                <cfset var exists = false>
                                <cflock scope="application" type="readonly" timeout="30">
                                <cfset exists = StructKeyExists(APPLICATION,"TrackerCFC")>
                                </cflock>
                                <cfif NOT exists> <!--- call this if onApplicationStart() hasn't processed --->
                                <cfset onApplicationStart()>
                                </cfif>
                                <cfset Super.onRequestStart(targetPage)>
                                <cflock scope="application" type="readonly" timeout="30">
                                <cfset REQUEST.TrackerCFC = APPLICATION.TrackerCFC>
                                <cfset REQUEST.TrackerService = APPLICATION.TrackerService>
                                </cflock>
                                <cfreturn true>
                                </cffunction>
                                • 13. Re: Application.cfc(s) and sharing values
                                  iKnowKungFoo Level 1
                                  It's not a bug. When a component extends another component, it inherits functions from the other component, but it also overrides any function of the same name.

                                  /Application.cfc
                                  /home.cfm
                                  /calendar/Application.cfc [ extends="Application" ]
                                  /calendar/showDay.cfm

                                  Both Application.cfc files have onApplicationStart() and onRequestStart()

                                  The root Application.cfc's onApplicationStart() creates the variable "application.mainObj".
                                  The calendar's Application.cfc onApplicationStart() creates the variable "application.calendarObj".

                                  If the very first page requested (the one that "starts" the application) is home.cfm, then onApplicationStart() runs in the root Application.cfc, "application.mainObj" is created and then onRequestStart() is called.

                                  If the very first page requested is showDay.cfm, then onApplicationStart() is called from the Application.cfc in the calendar folder. "application.calendarObj" is created, but "application.mainObj" is not and then onRequestStart() is called. In order to make sure that application.mainObj is created, you have to check inside onApplicationStart() in the same way I described in an earlier post for onRequestStart().

                                  <cfif not structKeyExists( application, "mainObj" )>
                                  <cfset super.onApplicationStart() />
                                  </cfif>

                                  Now when onApplicationStart() runs in the calendar folder, both application.mainObj and application.calendarObj are created.

                                  Then, in the onRequestStart() for the calendar's Application.cfc, you have to check if application.calendarObj exists and call its onApplicationStart() if necessary. In the case that the first page requested was home.cfm, onApplicationStart() is only ever run from the root Application.cfc. You have to specifically call the one in the calendar Application.cfc to execute its code.

                                  • 14. Re: Application.cfc(s) and sharing values
                                    Chuck1411 Level 1
                                    Thank you cf_menace, I implemented basically that exact thing, except did some cflock checks on application in addition. It's exactly what I needed, and it works flawlessly.