Fusebox not parsing xml files - coldfusion

Currently, in the application.cfc, I extend the Fusebox 5.5 Framework.
Then in the OnRequestStart method below, I set the fusebox mode depending on a certain condition.
The problem is that sometimes, the fusebox xml files do not reparse no matter what changes I make. If I force a reparse using the url variables fusebox.parse=true&fusebox.loadclean=true&fusebox.password=xxx then the files parse again.
It is almost like Fusebox remains in production mode even though when I dump the FUSEBOX_PARAMETERS.mode it says "development-full-load"
What could be causing this? Is the way that the fusebox mode is being manipulated correct in the code below or should that kind of setting be done somewhere else (besides the fusebox.xml obviously)??
Any help would be great.
Thanks
<cffunction name="onRequestStart">
<cfset variables.server_type = "Development" />
<cfswitch expression="#variables.server_type#">
<cfcase value="development">
<cfset FUSEBOX_PARAMETERS.mode = "development-circuit-load" />
<cfset FUSEBOX_PARAMETERS.debug = true />
<cfset request.component_reload = true />
</cfcase>
<cfdefaultcase>
<cfset FUSEBOX_PARAMETERS.mode = "production" />
<cfset FUSEBOX_PARAMETERS.debug = false />
<cfset request.component_reload = false />
</cfdefaultcase>
</cfswitch>
<cfif (StructKeyExists(attributes, "fusebox.loadapp") AND attributes.fusebox.password EQ application.fusebox.password) OR FUSEBOX_PARAMETERS.mode NEQ application.fusebox.mode>
<cfset this.onApplicationStart() />
</cfif>
<cfset superReturn = super.onRequestStart(arguments.1) />
</cffunction>

See, FUSEBOX_PARAMETERS are stored in application scope, by default they are included in huge container application.fusebox. Fusebox settings are populated when super.onApplicationStart() invoked, so modifying them in onRequestStart does not make sense.
I would recommend to move your cfswitch code into the component body where you define application settings.
In onRequestStart you can force the application restart to reread the settings, possibly something like this:
<cfif StructKeyExists(attributes, "fusebox.loadapp") AND attributes["fusebox.password"] EQ application.fusebox.password>
<cfset this.onApplicationStart() /
</cfif>
Please note that fusebox.loadapp is not built-in Fusebox attribute, it will work only for your app, simply prefixed like others for convenience. This way you can reread the singletones of your application.

Related

ColdFusion HELP Pages not Updating: My CF pages are still pointing to the original folder of my application

I have an existing ColdFusion application in my server. What I needed is a duplicate of that application. What I did was copy the entire folder of the original application and put it into another folder.
I already edited the Application.cfm and the links across all the pages in my copy. However, .../indexc.cfm?page=a_app_checklist - in this case, the a_app_checklist is not being updated even if I changed everything on my server /Copy/pages/app/a_app_checklist.cfm
I tried to upload the updated a_app_checklist.cfm on the original application and from there, it was updated. What should I do because I want my copy of the application to be a stand-alone from the original application.
Here is a part of my Application.cfm code:
<cfapplication name="Applicationv2" sessionmanagement="yes" setclientcookies="yes" sessiontimeout="#CreateTimeSpan(00,00,30,00)#"
applicationtimeout="#CreateTimeSpan(00,01,00,00)#" clientstorage="cookie" loginstorage="session">
<cfparam name="Url.page" default="a_main_index">
<cfparam name="Url.formpage" default="">
<cfparam name="Url.resetAppCache" default="">
<!--- Set the Application variables if they aren't defined. --->
<cfset app_is_initialized = False>
<cflock scope="application" type="readonly" timeout="5">
<cfset app_is_initialized = IsDefined("Application.initialized")>
</cflock>
<cfif not app_is_initialized>
<cflock scope="application" type="exclusive" timeout=10>
<cfif not IsDefined("Application.initialized")>
<!--- Do initializations --->
<cfset Application.StudentDB = "DB">
<cfset Application.Url = "/CopyOfApplication/">
<cfset Application.NSUrl = "/CopyOfApplication/">
<cfset Application.EmailLocation = "/CopyOfApplication/pages/email/">
<cfset Application.userfilespath = "/web_assets/UserFiles/">
<cfset Application.UnauthorizedFileExtentions = "ade,adp,asx,bas,chm,cmd,cpl,crt,dbx,exe,hlp,com,hta,inf,ins,isp,jse,lnk,mda,mde,mdz,mht,msc,msi,msp,mst,nch,pcd,prf,reg,scf,scr,sct,shb,shs,url,tmp,pif,dll,vb,vbs">
<cfset Application.ReportPage = "report.cfm">
<cfset Application.PrintPage = "print.cfm">
<!---Puts an instance of the user.cfc and system.cfc in the application scope. All pages can use it. --->
<cfobject type="component" name="Application.System" component="application.system">
<cfset Application.initialized = "yes">
</cfif>
</cflock>
<cfscript>
Application.System.LogActivity("Name","IP","Application scope variables initialized.");
</cfscript>
</cfif>
Like I said, the "page" part in the URL are the only ones that are not being updated. Does it mean I have problems with my URL.Page initialization?
Please let me know if you need additional code. I appreciate any input about this question. Thank you in advance! I am still learning ColdFusion and I will appreciate it if you will help me understand what I need to know!

Application.cfc vs Application.cfm and also the need to extend Application.cfc

I'm moving away from ColdFusion 8 to ColdFusion 10.
Currently, on my Unix's root directory, I only have 1 Application.cfm and under this root directory I have about 10 sub directories (previous programmers did it this way and I'm experiencing a lot of weird things).
Now that I get the chance to redo this web application, I want to do it properly but the biggest problem with me is to properly understand how to work with Application.cfc in CF10.
Each of the sub directory represents a web application. For example, there is a web application for tracking graduate students, a web app. for tracking alumni, a web app. for formatting addresses, etc.
Users for these applications are from 10 different institutions. They all login to the application the same way (from the same interface) but then we separate them using session.usergoup & session.username to know who is who and who can see what type of things.
All Institutions share the same database, so currently only the datasource is set to application scope.
Unfortunately after reading many Application.cfc postings at this forum I got even more confused, so I hope you guys don't mind assisting me so that I can feel more comfortable working with Application.cfc in CF10.
My understanding is:
On my root dir I will create one main Application.cfc. My Main Application.cfc will only handle login/user authentication.
So under this root dir, I will have 1 Application.cfc, loginform.cfm and loginaction.cfm
In loginaction.cfm is where I set session.usergroup and session.username upon successful user authentication.
So in my main Application.cfc, I should set the following:
<cfset THIS.Name = "InstitutionMainApp" />
<cfset THIS.ApplicationTimeout = CreateTimeSpan(0,0,30,0) />
<cfset THIS.SessionManagement = true />
<cfset THIS.SetClientCookies = false />
under OnApplicationStart I'll do:
<cfset application.dsn = "MyDB">
and under OnSessionStart I'll do:
<cfset session.usergroup= "">
<cfset session.username= "">
Then on each of my sub-folder's Application.cfc I need to name it differently
For graduate tracking system I should have:
<cfset THIS.Name = "GraduateTrackingSystem" />
<cfset THIS.ApplicationTimeout = CreateTimeSpan(0,0,30,0) />
<cfset THIS.SessionManagement = true />
<cfset THIS.SetClientCookies = false />
under OnRequestStart, when I need to encrypt url variable (form example), I can set:
<cfset request.mySecretKey = application.mySecretKey />
<cfset request.algorithm = "AES" />
<cfset request.encoding = "hex" />
For alumni tracking system I should have:
<cfset THIS.Name = "AlumniTrackingSystem" />
<cfset THIS.ApplicationTimeout = CreateTimeSpan(0,0,30,0) />
<cfset THIS.SessionManagement = true />
<cfset THIS.SetClientCookies = false />
under OnRequestStart, when I need to encrypt url variable (form example), I can set:
<cfset request.mySecretKey = application.mySecretKey />
<cfset request.algorithm = "AES" />
<cfset request.encoding = "hex" />
For Address Formating app., I should set:
<cfset THIS.Name = "AddressFormattingSystem" />
<cfset THIS.ApplicationTimeout = CreateTimeSpan(0,0,30,0) />
<cfset THIS.SessionManagement = true />
<cfset THIS.SetClientCookies = false />
under OnRequestStart, when I need to encrypt url variable (form example), I can set:
<cfset request.mySecretKey = application.mySecretKey />
<cfset request.algorithm = "AES" />
<cfset request.encoding = "hex" />
Then since the application.dsn, session.usergroup and session.username are all set in
the Main Application.cfc under the root dir., I can freely use these scoped variables
on each application sub-folder safely because each of sub-folder application.cfc is
named differently this way I should not be concern with cross reference among usergroup
and username?
Please let me know if my understanding on how to use Application.cfc is very much a
mess.
That's a long question.
I think this is what you need: http://corfield.org/blog/index.cfm/do/blog.entry/entry/Extending_Your_Root_Applicationcfc
Once you have extended your application.cfc via some proxy to workaround the limitation of extending itself, you should be able to do almost anything your existing application.cfm was setup to do.
update: as iKnowKungFoo pointed out in the comment, once you have a different application name i.e. this.name you cannot share the vars in the Application scope since you're essentially forking a new application, you may try Server scope for those. Logic can be shared via functions you have inherited, but pay attention to whether the vars are accessible in your application.

Unable to access variables when converting from application.cfm to application.cfc

I am trying to convert an application I support from application.cfm to application.cfc. I followed Ben Nadel's ColdFusion Application.cfc Tutorial And Application.cfc Reference, but my pages cannot access any of the variables in the APPLICATION scope, without adding APPLICATION. to the variable. As a side note, this application uses 0 cfc's currently.
here is my application.cfc.
<cfcomponent displayname="Application" hint="Handle the application" output="true">
<cfset THIS.Name = "AAS" />
<cfset THIS.ApplicationTimeout = CreateTimeSpan( 0, 60, 0 , 0) />
<cfset THIS.SessionManagement = true />
<cfset THIS.setClientCookies = false />
<cfset THIS.versionNum = '1'>
<cfset THIS.genericUserID = 'o005265'>
<cfset THIS.genericPassword = 'zo005265'>
<cffunction
name="OnApplicationStart"
hint="Fires when the application is first created."
access="public"
output="false"
returntype="boolean">
<cfset APPLICATION.aasURL = 'http://127.0.0.1:8500/aaas'>
<cfset APPLICATION.dsn = 've0_aaas'>
<cfset APPLICATION.aas_system = 'development (studio)'>
<cfreturn true />
</cffunction>
</cfcomponent>
Basically I just copied what was in the application.cfm page, and figured it would work the same. I am guessing that I have to invoke this somewhere? That is the only thing that I can think of. Any help would be great.
--- EDIT ---
I have added the OnRequest and OnApplicationStart methods after #EvikJames answer
<cffunction name="OnApplicationStart" access="public" returntype="boolean" output="false" hint="Fires when the application is first created.">
<!--- Return out. --->
<cfset APPLICATION.aasURL = 'http://127.0.0.1:8500/aaas'>
<cfset APPLICATION.datasource = 've0_aaas'>
<cfset APPLICATION.aas_system = 'development (studio)'>
<cfreturn true />
</cffunction>
<cffunction name="OnRequest" access="public" returntype="void" output="true" hint="Fires after pre page processing is complete.">
<!--- Define arguments. --->
<cfargument name="TargetPage" type="string" required="true">
<!--- Include the requested page. --->
<cfinclude template="#ARGUMENTS.TargetPage#" />
<cfset VARIABLES.dsn = APPLICATION.dsn>
<cfset VARIABLES.aasURL = APPLICATION.aasURL>
<cfset VARIABLES.aas_system = APPLICATION.aas_system>
<!--- Return out. --->
<cfreturn />
</cffunction>
You aren't really trying to use "application" variables (which always need to be scoped). I suspect your old application.cfm page had something like.
<cfapplicatin name="blah"...>
<cfset dsn = 'mydsn'/>
And then you were able to do:
<cfquery datasource="#dsn#">
This approach does not utilze the application scope ... it is merely taking advantage of the fact that your application.cfm always runs no matter what. What it is actually doing is putting variables in the variables scope. Because CF always checks the "variables" scope first you soemthing like #dsn# works - but that is not the same as the application scope.
To mimic this behavior in Application.cfc (as has been suggested) you will need to put your variable in the "onRequest()" function instead of the "onApplicationstart()" function - like so:
<cffunction name="onRequest">
<cfset dsn = 'mydsn'/>
</cffunction>
That is expected. To reference application variables you need to prefix them with application.
In your onApplication start method, do this:
<cfset APPLICATION.datasource = 'MyDSN'>
In your onRequest method, do this:
<cfset VARIABLES.DSN = APPLICATION.datasource>
Then, this query will work:
<cfquery datasource="#dsn#">
// sql
</cfquery>
I should add that when you are fully upgraded, you can remove all of the code above just set the default datasource:
<cfset THIS.datasource = 'MyDSN'>
If the variable is in the application scope, you will always need to identify it that way in your .cfm pages. If you use a variable name without the scope prefix, the application scope is not looked at.
if you want to declare variables in the application.cfc that can be accessed without the application scope in your other pages, simply declare the variables outside of any functions.
<component>
<cfset this.name = "applicationName">
<cfset otherVar = 'something'>
<cfset otherVar2 = 'something else'>
<cffunction name="onApplicationStart>.....</cffunction>
</component>
otherVar and otherVar2 can be called without scope prefix on all .cfm pages.
It sounds like you were not originally using application scoped variables. If the variables were not originally scope with "application." then they were simply in "variables scope" (confusing wording I know) which is accessible by the cfm page hit and others included. That is one big change when moving between application.cfm and application.cfc. The general idea there follows the principle that included CFM files share variables scope and CFC files do not.
If the only change you have to make is changing #dsn# to #appplication.dsn# then just do it and get it over with. There are tools such as WinGrep or even Notepad++ which have find and replace across multiple files.

How to best create and store APPLICATION variables?

I am using ColdFusion 9.0.1
I am taking over a site and the guy before me created about 100 variables and put them into the APPLICATION scope. I believe that his 100 variables were continuously being overwritten with each page load.
Basically, he had this in Application.cfc:
APPLICTION.VariableOne = "SomeStringOne";
APPLICTION.VariableTwo = "SomeStringTwo";
APPLICTION.VariableThree = "SomeStringThree";
My plan is to keep it simple and yet very readable is to test for a specific structure in the application scope. If it's not there, create the structure and variables:
if (not isDefined("APPLICTION.AppInfo") or not isStruct(APPLICTION.AppInfo)) {
APPLICTION.AppInfo = structNew();
APPLICTION.AppInfo.VariableOne = "SomeStringOne";
APPLICTION.AppInfo.VariableTwo = "SomeStringTwo";
APPLICTION.AppInfo.VariableThree = "SomeStringThree";
}
Of course, once the site is live and we are done creating all of the application variables, I'd move this into the into the onApplicationStart() method.
The solution that I want has to be more about "readability" and less about "efficiency". Several non-CFers, but very experience coders will be using this and will need to "get it" quickly.
Does my plan have any gaping holes or is it too inefficient?
Is there a more readable way of creating and managing application variables?
Why not move the definition into onApplicationStart() right now? If you need to reset them during development, you could always pass in a URL variable to flag it for reset, like so:
<!--- in Application.cfc --->
<cffunction name="onRequestStart">
<cfif IsDefined("url.resetApp")>
<cfset ApplicationStop()>
<cfabort><!--- or, if you like, <cflocation url="index.cfm"> --->
</cfif>
</cffunction>
Actually, after re-reading the OP, and reading the suggested solutions, I'm going to have to agree with the OP on his setup, for this very important reason:
This, in onApplicationStart()
APPLICTION.AppInfo = structNew();
APPLICTION.AppInfo.VariableOne = "SomeStringOne";
APPLICTION.AppInfo.VariableTwo = "SomeStringTwo";
Can then later be turned into this, within onRequestStart()
<cflock name="tmp" type="readonly" timeout="15">
<cfset REQUEST.AppInfo = APPLICATION.AppInfo />
</cflock>
Your app can then go on to access the REQUEST vars conveniently, esp, if you decide you want to cache CFCs in the same scope--they would simply go into a separate key:
APPLICATION.Model.MyObject = CreateObject('component','myobject');
Which, of course, also gets poured into REQUEST (if you choose)
Want to go Jake Feasel's route above? No problem:
<cfif isDefined('URL.reload')>
<cfset APPLICATION.Model = StructNew() />
</cfif>
Now you're able to flexibly kill your object cache but maintain your vars (or vice versa as you choose).
This is a great setup for another reason: If you want to build in your own Development/Production "mode", in which the development mode always recompiles the CFCs, but the production mode keeps them cached. The only change you have to make on top of this, is the REQUEST set noted above:
<cfif (isProduction)>
<cflock name="tmp" type="readonly" timeout="15">
<cfset REQUEST.AppInfo = APPLICATION.AppInfo />
</cflock>
<cfelse>
<cfset REQUEST.AppInfo = StructNew() />
<cfset REQUEST.AppInfo.VariableOne = "SomeStringOne" />
...etc...
</cfif>
You can also make the setting of vars and the creation of objects into a private method within Application.cfc, for even further convenience.
I would go ahead and just use OnApplicationStart but back in the pre Application.cfc days we used to do something like Application.Build and if the Build value was different then we did all of our sets on Application variables. So quick and dirty would be something like:
<cfparam name="Application.Build" default="" />
<cfset Build = "28-Nov-2011" />
<cfif Application.Build IS NOT Variables.Build OR StructKeyExists(URL, "Rebuild")>
<cfset Application.Build = Variables.Build />
<!--- A bunch of other CFSETs --->
</cfif>
This method though was something we used back when all we had was the Application.cfm

Global Variables in ColdFusion

2 Questions -
In CF8 in the application.cfm I cold set a global variable
like so
<cfset DSN = "dej6_42">
I am now trying to adjust to the Application.cfc in CF10/Lucee and can not figure out how to set this same variable.
Here is my current Application.cfc
<cfcomponent output="false">
<cfset This.name = "My Application">
<cfset This.clientmanagement="True">
<cfset This.loginstorage="Session">
<cfset This.sessionmanagement="True">
<cfset This.sessiontimeout="#createtimespan(0,0,10,0)#">
<cfset This.applicationtimeout="#createtimespan(5,0,0,0)#">
<cfset DSN = "dej6_42">
</cfcomponent>
I have tried
<cfset This.DSN = "dej6_42">
Then tried to call in a separate page
<cfoutput>#Applicaton.DSN#</cfoutput>
I think from my research I will need to use both application.cfc and application.cfm to accomplish the above. *edit - I tried to add an include at the end of the application.cfc file to applciation.cfm and it did not work.
2 Question.
When I place any of the standard functions in the Application.cfc my site turns to a blank page
Here is that Application.cfc - I if I remove everything below the DSN set then it will display the site.
<cfcomponent output="false">
<cfset This.name = "My Application">
<cfset This.clientmanagement="True">
<cfset This.loginstorage="Session">
<cfset This.sessionmanagement="True">
<cfset This.sessiontimeout="#createtimespan(0,0,10,0)#">
<cfset This.applicationtimeout="#createtimespan(5,0,0,0)#">
<cfset DSN = "dej6_42">
<cffunction name="onApplicationStart">
</cffunction>
<cffunction name="onApplicationEnd">
</cffunction>
<cffunction name="onRequestStart">
</cffunction>
<cffunction name="onRequest">
</cffunction>
<cffunction name="onRequestEnd">
</cffunction>
<cffunction name="onSessionStart">
</cffunction>
<cffunction name="onSessionEnd">
</cffunction>
<cffunction name="onError">
</cffunction>
</cfcomponent>
Your example doesn't set a global variable. It sets a variable in the variables scope: it will not be accessible to any CFC-based code nor any custom tags used within the request. It'll only be available in the Application.cfm, the file requested, files it includes, and OnRequestEnd.cfm
Application.cfc is a CFC (to state the obvious), so variables-scoped variables set within it are only available within it. If you want to set an application-wide variable, you need to put it in the application scope. Application scope variables should be set in the onApplicationStart) handler which is run once when the application starts, but not on every request. By way of comparison Application.cfm (which is misnamed) is run on every request. It should be called OnRequestStart.cfm.
So to be clear, setting an application-scoped variable in onApplicationStart would be as thus:
function onApplicationStart() {
application.DSN = "dej6_42";
}
If you use an onRequest() interceptor, and within that include the originally requested file, then the request will be run in the context of the Application.cfc instance, and variables set within onRequest will be available to the rest of the mainline request code, much like the way you set your variable in Application.cfm. Semantically though, if you mean a variable to exist for the life of the application (like a DSN), then putting it in the application scope is the best bet.
It sounds to me from the inferences one can make from your question that your app architecture might be languishing in the 1990s. I think you should read up on using a framework (eg: FW/1 or ColdBox) to better organise your code in a maintainable and scalable way.
Also you should read up on Application.cfc (and method reference). And probably CFCs in general: Using ColdFusion components-Developing guide.
You also might want to think about modernising your approach to writing CFML and spare the tags for view code, and otherwise using script. It makes the code easier to follow for both you and other developers who might end up needing to maintain it if the whole app isn't cluttered up with tags.
You need to set it into the application scope
<cfcomponent output="false">
<cfset This.name = "My Application">
<cfset This.clientmanagement="True">
<cfset This.loginstorage="Session">
<cfset This.sessionmanagement="True">
<cfset This.sessiontimeout="#createtimespan(0,0,10,0)#">
<cfset This.applicationtimeout="#createtimespan(5,0,0,0)#">
<cfset application.DSN = 'dej6_42'>
</cfcomponent>