Does Coldfusion have a "Global" structure where the expressions global["FORM"], global["URL"], global["APPLICATION"], global["SESSION"], etc. are valid?
no. Form, URL, Application, Session etc are all 'global' already. The underlying Java has got this, if you just want to dump out all the scopes at once:
<cfdump var="#getPageContext().getBuiltInScopes()#">
Or at least that used to work, but in CF9 you have to use this instead:
<cfdump var="#getPageContext().getCFScopes()#">
Sorry, but the answer is, "Nope." (am I up to 30 characters yet?)
My take is that you are out of luck with FORM and URL scope.
You can access all user sessions running on a CF instance using SessionTracker Java object:
<cfset sessionTrackerObj = createObject("java","coldfusion.runtime.SessionTracker")>
<cfoutput><p>There are #sessionTrackerObj.getSessionCount()# active sessions</p></cfoutput>
Dump the sessionTrackerObj to view its structure.
The same goes for the APPLICATION scope:
<cfset appTrackerObj = createObject(“java”,”coldfusion.runtime.ApplicationScopeTracker”)>
Enjoy!
Related
In our Portal application.cfc, we are defining (setting up) our DSN connections like so:
<cfset this.datasource = "DSN1"> (Main DB)
<cfset this.datasource_1 = "DSN2"> (2nd DB)
<cfset this.datasource_2 = "DNS3"> (3rd DB)
These are in the tags. I have also moved then to the ‘OnApplicationStart’ function and cannot get it to work correctly.
This application.cfc if referenced in the main APP, that the other apps have access to (App2, etc…), my question is;
How do I reference the other datasources (this.datasource_2) in a query for the App2 application?
<cfquery name="queryname" datasource="**[What goes here]**"> For second datasource
The this.datasource DSN is always being referenced because there is no datasource listed in the cfquery tags.
Any help you can provide or links to send my way will be appreciated. Thanks in advance!
Try seeing additional application variables
<cfset application.datasource_1 = "DSN2"> (2nd DB)
<cfset application.datasource_2 = "DNS3"> (3rd DB)
My solution is to not use any variables at all and simply hard code the datasource names. In other words, for this:
<cfquery name="queryname" datasource="**[What goes here]**"> For second datasource
The answer is "DSN2".
In order for these datasources to be usable, they have to be defined on the server and you have to know their names. If you assign them to some sort of global variable, then you would have to know the name of that variable. I see no value to using global variables in this situation.
For DSN1, there are pros and cons to using a global variable. The advantage of a variable is that you don't need a datasource attribute for the queries that use this database. The disadvantage is that your code becomes a little less consistent if some queries have a datasource attribute and others don't. That topic is best discussed in person while drinking beer.
or you can use the Applicaton.cfc this.datasources struct
I've a variable in my Application.cfm that stores the datasource for cfqueries.
<cfset mydatasource= 'somedatasorce'>
I can use it in any normal cfm page as below:
<cfset any_var = #mydatasource#>
I've a cfm page that calls a cfc which builds a query dynamically. This is the URL Invocation Method of CFC.
I'm not able to access "mydatasource" in the CFC using the above statement. It says "mydatasource" is undefined. I tried storing this in Application scope & accessed in CFC but again it says "mydatasource" is undefined in "Application".
On a bit of search, I found that the CFC needs to be instantiated in order to access the Application scope. But the URL Invocation method doesn't create an instance.
I can pass the datasource using query string but I'm looking for a better & more secure alternative.
Any suggestions are highly appreciated.
Thanks!! :)
I have been adding a number of ajax calls to an old application here and in order to get some application specific settings I created a file I called App.cfc. The contents of it are simply:
<cfcomponent>
<cfscript>
this["datasource"] = "something";
..... and so on .....
</cfscript>
</cfcomponent>
Then the CFC files I am making my URL calls to they simple extend App. So within those CFCs I can do datasource="#this['Datasource']#"
May not be the most "pretty" of ways to get the job done but it has been working here without issues.
UPDATE
I should have also mentioned that in order to avoid having settings in both that CFC and in the Application.cfm, I have something like this in my Application.cfm:
<cfscript>
objApp = CreateObject("component", "Components.App");
StructAppend(App, objApp);
</cfscript>
These old applications I am working with have a structure withing VARIABLES called App that is a copy of all Application variables. I see no reason why in this case you could not just do a structure appending to VARIABLES since appears that is where you are expecting things like the datasource to be on in your CFM pages.
How can I pass a variable to a cfm page that I'm including from another page?
Example:
<cfset a.name = "me">
<cfset a.age = 135>
<cfinclude template="displayNameAndAgeFrom_A.cfm">
and displayNameAndAgeFrom_A.cfm is
<cfoutput>#a.name# #a.age#</cfoutput>
Thanks!
AFAIK, this should work, exactly the way you posted it, without having to pass anything at all. Any values available in the outside/calling page are available in the included page.
Also worth noting that you also have <cfmodule ... /> available. cfmodule will let you call the same template but you can pass in different values for the same attributes.
Check out ColdFusion 9 documentation on cfmodule.
This template/module however will only have access to a handful of scopes that the caller template has access to: request, session and application
I have in my cfm something like this
<CFModule name="MyModule"
someParam_one="#something.one#"
someParam_two="#something.two#"
someParam_etc="etc_etc_etc"/>
And inside my module, I have an
<CFSet param_name = "someParam_one">
...
evaluate("attributes." & param_name)
On most of our servers, this work. But on one of our servers, I get a
Error resolving parameter ATTRIBUTES.SOMEPARAM_NAME
Any ideas why?
Thanks
Have you verified that someParam_one is actually getting created? I've found, for example, that if I do something like this:
<cfset foo = myObject.getSomething() />
and getSomething returns a void value or runs a Java function that doesn't return anything, that CF will choke on it. The variable will be "defined", or so the application seems to think, but attempting to access it will throw an error. So do the following to track down and catch the problem:
Dump your attributes scope to make sure that what you want is indeed actually there.
Run a StructKeyExists(Attributes, param_name) before attempting to access the variable.
Get rid of the evaluate, and instead use Attributes[param_name]
Tangential to your question, but Evaluate() is evil, and an unnecessary evil in this situation. You can write this instead, and it will be more clear, more secure, and faster:
<cfset param_name = "someParam_one">
...
<cfset param_value = Attributes[param_name]>
A shot in the dark:
There's a bug in CFMX where if you
make a CFMODULE call to a template (or
use custom tag) from within a CFC and
that tempate uses the CALLER scope to
return data, the data is never
available to the CFC function. This is
bug 51067 and it is related to the
VARIABLES scope bug, 45138.
Seen in the user comments in the CFMX 6 docs on CFMODULE.
Ok, we did something really stupid :-)
We had two set of these files deployed and one was updated while the other was not, thus the error.
Thanks for all your help.
Been going over my predecessor's code and see usage of the "request" scope frequently. What is the appropriate usage of this scope?
There are several scopes that are available to any portion of your code: Session, Client, Cookie, Application, and Request. Some are inadvisable to use in certain ways (i.e. using Request or Application scope inside your Custom Tags or CFC's; this is coupling, violates encapsulation principles, and is considered a bad practice), and some have special purposes: Cookie is persisted on the client machine as physical cookies, and Session scoped variables are user-specific and expire with the user's session on the website.
If a variable is extremely unlikely to change (constant for all intents and purposes) and can simply be initialized on application startup and never written again, generally you should put it into Application scope because this persists it between every user and every session. When properly implemented it is written once and read N times.
A proper implementation of Application variables in Application.cfm might look like this:
<cfif not structKeyExists(application, "dsn")>
<cflock scope="application" type="exclusive" timeout="30">
<cfif not structKeyExists(application, "dsn")>
<cfset application.dsn = "MyDSN" />
<cfset foo = "bar" />
<cfset x = 5 />
</cfif>
</cflock>
</cfif>
Note that the existence of the variable in the application scope is checked before and after the lock, so that if two users create a race condition at application startup, only one of them will end up setting the application variables.
The benefit of this approach is that it won't constantly refresh these stored variables on every request, wasting the user's time and the server's processing cycles. The trade-off is that it is a little verbose and complex.
This was greatly simplified with the addition of Application.cfc. Now, you can specify which variables are created on application startup and don't have to worry about locking and checking for existence and all of that fun stuff:
<cfcomponent>
<cfset this.name = "myApplicationName" />
<cffunction name="onApplicationStart" returnType="boolean" output="false">
<cfset application.dsn = "MyDSN" />
<cfset foo = "bar" />
<cfset x = 5 />
<cfreturn true />
</cffunction>
</cfcomponent>
For more information on Application.cfc including all of the various special functions available and every little detail about what and how to use it, I recommend this post on Raymond Camden's blog.
To summarize, request scope is available everywhere in your code, but that doesn't necessarily make it "right" to use it everywhere. Chances are that your predecessor was using it to break encapsulation, and that can be cumbersome to refactor out. You may be best off leaving it as-is, but understanding which scope is the best tool for the job will definitely make your future code better.
This is a very subjective question, and some would even argue that it is never "appropriate" to use the request scope in modern ColdFusion applications.
With that disclaimer out of the way, let's define what the request scope is and where it would be useful.
The request scope is the absolute global scope in a single ColdFusion page request. It is not a shared scope, like application, server, client, and session scopes, so locking is not necessary to make it threadsafe (unless you spawn worker threads from a single request using CF8's CFTHREAD tag). As a global scope, it is a very convenient way to persist variables through any level in the request's stack without having to pass them from parent to caller. This was a very common way to persist variables through nested or recursive Custom Tags in older CF apps.
Note that while many applications use this scope to store application-level variables (configuration settings, for example), the big (and sometimes subtle) difference between the request scope and the application scope is that the value of the same request-scoped variable can differ between individual page requests.
I would guess that your predecessor used this scope as a means to conveniently set variables that needed to survive the jump between encapsulated or nested units of code without having to pass them around explicitly.
Okay, I just wanted to comment on your code. Please forgive me if I seem crazy. But you already verified that the structKeyExists in the beginning. Since you know it's going to be true, it wouldn't make sense to run another check. So my version of it would be this... But thats just me.
<cfif not structKeyExists(application, "dsn")>
<cflock scope="application" type="exclusive" timeout="30">
<cfset application.dsn = "MyDSN" />
<cfset foo = "bar" />
<cfset x = 5 />
</cflock>
</cfif>
Alright.
I've been writing my company's framework that will be used to power our site.
I use the request variable to set certain data that would be available to the other CFC's I had to do this so the data would be available throughout the application, without the need to continually pass in the data. I honestly believe that using request , and application as long as its a static function component then you should not have a problem. I'm not sure if I am wrong in my thinking with this but once I release the framework we will see.