ColdFusion - When to use the "request" scope? - coldfusion

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.

Related

How to call a function from another function using the reference of object of a cfc?

Sorry about the question phrase. I couldn't find better way to describe it. But my problem is as follows:
I have 3 cfc's namely settings.cfc, prices.cfc and helpers.cfc. These cfc's extend 4th cfc controller.cfc.
The helper.cfc is as follows:
<cfcomponent extends="Controller">
<cffunction name="formatCurrency">
<cfset formattedCurrency = 1 />
<cfreturn formattedCurrency>
</cffunction>
<cffunction name="processTemplateVariables">
<cfargument name="templateText" default="defaultText" >
<cfset formatCurrency() />
<cfreturn formattedCurrency >
</cffunction>
</cfcomponent>
The settings.cfc has a setApplicationVariables method which we use to set the application level variables. In this cfc, i have created an object of helpers.cfc and put that object into the application scope. The settings.cfc is as follows:
<cfcomponent extends="Controller">
<cffunction name="setApplicationVariables">
<cfset application.helpers = createObject("component","controllers.Helpers") />
</cffunction>
</cfcomponent>
The settings.cfc gets invoked on application start which in turn creates a object of helpers.cfc and put it into the application scope.
We create a reference to the method ProcessTemplateVariables in the controller.cfc as follows:
<cfcomponent extends="Wheels">
<cfset getFormattedCurrency = application.helpers.processTemplateVariables >
</cfcomponent>
In the prices.cfc, we use this reference to call the function processTemplateVariables, which it does. But it does not call the function formatCurrency that is called inside from the processTemplateVariables and it throws error "variable formatCurrency is undefined".
But if i use the application.helpers.processTemplateVariables(templateText="someText"), it works.
It also works, when i use cfinvoke as bellow:
<cfinvoke method="processTemplateVariables" component="controllers.helpers" templateText="someText" returnvariable="content">
The prices.cfc is as follows:
<cfcomponent extends="Controller">
<cffunction name="index">
<!--- does not work, throws 'the formatCurrency() variable is undefined' --->
<cfdump var="#getFormattedCurrency("someText")#"><cfabort>
<!--- works --->
<cfinvoke method="processTemplateVariables" component="controllers.helpers" templateText="someText" returnvariable="content">
<!--- works --->
<cfset application.helpers.processTemplateVariables("someText") />
</cffunction>
</cfcomponent>
I am not sure why using reference is not working.
Sorry about the earlier confusion but your comments made me dig deeper and i could found out that it was reference that was culprit. Is there any way to make this work with reference, that would be cool?
Update:
This blog entry (by Adam Cameron) has a better description. To summarize:
.. it pulls the method out of the CFC, so it will be running in the
context of the calling code, not the CFC instance. Depending on the
code in the method, this might or might not matter.
In your specific case it does matter. The function has a dependency on formatCurrency, which does not exist in the "context" of the calling page, and that is why you get an "undefined" error.
(From comments)
Yeah, I am pretty sure you cannot do that. Each function is compiled into an individual class: specifically a static inner class. (You can see the inner class names if you dump out the function name without parenthesis ie #application.helpers.formatCurrency#) In other words, it is disconnected from any specific instance - and by extension - the other functions.
When you create an instance of the component, all of the functions are stored its variables scope. So when you invoke "processTemplateVariables" - from within the instance - it has access to the other functions via the component's variables scope. When your code creates a reference to that function, what you are actually getting is completely disconnected from the parent instance ie application.helpers. So it won't have access to any of the other functions. Hence why you get an "undefined" error.
The limitation is understood well from the answer by Leigh.
To focus on your requirement here: using a short name alias for the functions, You can still use your original code, with a little trick of adding all the dependent functions as a reference, so that they are available inside the controller.cfc scope similar to the getFormattedCurrency.
Edit 1:
<cfcomponent extends="Wheels">
<cfset getFormattedCurrency = application.helpers.processTemplateVariables />
<cfset formatCurrency = application.helpers.formatCurrency />
</cfcomponent>
Now, for the fun part, it's quite possible to access a function from another cfc and still preserve all the dependencies. I was surprised as well when I recalled an amazing post by Bennadel here. This is simply amazing. But to warn you this practice is discouraged. So I took up with your setup and went ahead anyway. And it all worked like a charm with no issues encountered so far(but I'm quite sure there could arise some complications).
The point of problem with original usage was that the function has a dependency on formatCurrency, which does not exist in the "context" of the calling page as educated by Leigh in his answer.
So what if you can just copy scoped objects or even the functions from another component to you controller.cfc, sounds weird and amazing at the same time but it's possible using the <cfinclude> tag inside the controller.cfc (note: not encouraged) based upon the idea what Bennadel used for his example.
Edit2:
Your controller.cfc should look something like this:
<cfcomponent extends="Wheels">
<!--- Placed inside the controller's scope itself, outside every other function --->
<cfinclude template="helpers.cfc" />
....<rest of your code>....
...........
</cfcomponent>
Note that you don't even need to create a short-hand alias for the functions now. All the components and views can directly use the function name as you intended.
No need to point out that there would be chances of Naming collision if any other component extending the Controller.cfc has a function with the same name as any of the function inside the component library that is being imported. But those can be solved by following more specialization for the functions into multiple components OR as simple as using a prefix as a part of the coding standard to the function names to avoid any such future scenarios.

What's the correct way to allow different ColdFusion CFC's to instance each other?

I have a “best-practices” question in regards to the correct way to instance CFCs that all need to talk to each other in a given project.
Let’s say for example you have a web application that has a bunch of different modules in it:
Online Calendar
Online Store
Blog
File Manager (uploading/downloading/processing files)
User Accounts
Each of these modules is nicely organized so that the functions that pertain to each module are contained within separate CFC files:
Calendar.cfc
Store.cfc
Blog.cfc
Files.cfc
Users.cfc
Each CFC contains functions appropriate for that particular module. For example, the Users.cfc contains functions pertaining to logging users on/off, updating account info etc…
Sometimes a CFC might need to reference a function in another CFC, for example, if the store (Store.cfc) needs to get information from a customer (Users.cfc). However, I'm not sure of the correct way to accomplish this. There are a couple ways that I've been playing with to allow my CFC's to reference each other:
Method 1: Within a CFC, instance the other CFC’s that you’re going to need:
<!--- Store.cfc --->
<cfcomponent>
<!--- instance all the CFC’s we will need here --->
<cfset usersCFC = CreateObject("component","users") />
<cfset filesCFC = CreateObject("component","files") />
<cffunction name="storeAction">
<cfset var customerInfo = usersCFC.getUser(1) />
This approach seems to work most of the time unless some of the instanced CFC’s also instance the CFC’s that instance them. For example: If Users.cfc instances Files.cfc and Files.cfc also instances Users.cfc. I’ve run into problems with occasional dreaded NULL NULL errors with this probably because of some type of infinite recursion issue.
Method 2: Instance any needed CFCs inside a CFC’s function scope (this seems to prevent the recursion issues):
<!--- Store.cfc --->
<cfcomponent>
<cffunction name="storeAction">
<!--- create a struct to keep all this function’s variables --->
<cfset var local = structNew() />
<!--- instance all the CFC’s we will need here --->
<cfset local.usersCFC = CreateObject("component","users") />
<cfset local.filesCFC = CreateObject("component","files") />
<cfset var customerInfo = local.usersCFC.getUser(1) />
My concern with this approach is that it may not be as efficient in terms of memory and processing efficiency because you wind up instancing the same CFC’s multiple times for each function that needs it. However it does solve the problem from method 1 of infinite recursion by isolating the CFCs to their respective function scopes.
One thing I thought of based on things I've seen online and articles on object oriented programming is to take advantage of a “Base.cfc” which uses the “extends” property of the cfcompontent tag to instance all of the CFC's in the application. However, I've never tested this type of setup before and I'm not sure if this is the ideal way to allow all my CFCs to talk to each other especially since I believe using extends overwrites functions if any of them share a common function name (e.g. "init()").
<!--- Base.cfc --->
<cfcomponent extends="calendar store blog users files">
What is the correct "best-practices" method for solving this type of problem?
If each of your CFC instances are intended to be singletons (i.e. you only need one instance of it in your application), then you definitely want to looking into Dependancy Injection. There are three main Dependancy Injection frameworks for CF; ColdSpring, WireBox and DI/1.
I'd suggest you look at DI/1 or WireBox as ColdSpring hasn't been updated for a while.
The wiki page for DI/1 is here:
https://github.com/framework-one/di1/wiki/Getting-Started-with-Inject-One
Wirebox wiki page is here:
http://wiki.coldbox.org/wiki/WireBox.cfm
Essentially what these frameworks do is to create (instantiate) your CFCs (beans) and then handles the dependancies they have on each other. So when you need to get your instantiated CFC it's already wired up and ready to go.
Dependancy Injection is also sometimes called IoC (inversion of control) and is a common design pattern used in many languages.
Hope that helps and good luck!
If your cfcs not related to each other the base.cfc concept does not fit. The inheritance is for classes have common things that can inherit from each other. For example if you have User.cfc and you want to added new cfc called customer.cfc I would inherit from User and override some functionality or add some without touching the actual user.cfc.
So, back to your question, since the CFC are not related or have common between each other and to avoid cross referencing, I will create serviceFactory holds instances of cfcs like this
component name="ServiceFactory"
{
function init(){
return this;
}
public User function getUserService(){
return new User();
}
public Calendar function getCalendar(){
return new Calendar();
}
}
and referencing it by
serviceFactory= new ServiceFactory();
userService = serviceFactory.getUserService();
Keep in mind this approach works only if you have sort of another CFC to manage your logic
you can do the same for all other services. If your functions are static you can save your services in application scope and instantiate it only one time (like singleton).
The third option you have is DI(dependency Injection) framework

null null error in SERVER structure

I have a SERVER variable, a structure of structures, which is highly accessed by all users (concurrency). Values are added and deleted very very frequently. Here is a small example of my SERVER variable. The real one has much more data.
<cfset SERVER.structure = StructNew()>
<cfset s = StructNew()>
<cfset StructInsert(s, 'test11', 'value11', true)>
<cfset StructInsert(s, 'test12', 'value12', true)>
<cfset StructInsert(SERVER.structure, 'test1', s, true)>
<cfset s = StructNew()>
<cfset StructInsert(s, 'test21', 'value21', true)>
<cfset StructInsert(s, 'test22', 'value22', true)>
<cfset StructInsert(SERVER.structure, 'test2', s, true)>
Every couple of hours, I loop this structure to clean expired data. However, I am getting the error "null null" while looping the variable like this:
<cfloop collection="#SERVER.structure#" item="key">
<cfif StructKeyExists(SERVER.structure, key)>
<cfloop collection="#StructFind(SERVER.structure, key)#" item="key2">
<!--- And some code here --->
</cfloop>
</cfif>
<cfif StructCount(StructFind(SERVER.structure, key)) eq 0>
<cfset StructDelete(SERVER.structure, key, false)>
</cfif>
</cfloop>
I'm receiving the error in the first line of the example. In this line, exactly:
<cfloop collection="#SERVER.structure#" item="key">
So I tried another approach. Instead of looping one by one, I created an array of keys and looped it. Unfortunately, the "null null" error was also happening there, in this exact line:
<cfset arrayOfKeys = StructKeyArray(SERVER.structure)>
My first theory is that ColdFusion can't handle the concurrency level that this SERVER variable has. I tried to use a <cflock> here, while clearing the variable, but it didn't work either. And I can't have this <cflock> where the variable is actually being used and modified by users because of the extra load that it would add (I believe).
I don't know... I'm out of ideas. Does anyone now why is this happening or have suffered this problem before? And a solution or workaround to this problem, or even a suggestion to make my code better, would be more than welcome too.
Thank you very much.
I tried to use a <cflock> here, while clearing the variable, but it
didn't work either. And I can't have this <cflock> where the variable
is actually being used and modified by users because of the extra load
that it would add (I believe).
This is your problem. If you are using the server scope, you must lock all access to it (read and write). Otherwise you will get errors. That's the long and the short of it.
My first theory is that ColdFusion can't handle the concurrency level that this SERVER variable has
Well: no. ColdFusion will synchronise individual operations to the server scope (well: it's handled at Java level), and that's where its job begins and ends. It's just that your approach doesn't handle it. Namely that you don't take steps to mitigate race conditions in your own code. This assertion of yours:
I am not locking access when I work with the variable because collisions can't happen
Is just wrong. There's a race condition in your loop.
As others have hinted at, this is very poor application architecture, and the code is facile.
Just put the data in a database. That's what databases are for, and they're written in such a way to optimise the sorts of operation you are trying to (but not succeeding, obviously) to achieve here.
I think this is probably a case of premature optimisation: have you had this data in a properly provisioned and designed DB? Or are you second-guessing that it will be a problem? I suspect it's the latter. Or that the DB server was not properly provisioned.
Over and above the database tier, you could also use a caching tier like others have suggested.
But just don't reinvent the wheel, like others have said.
The bottom line answer to your question is that you're getting the errors because you are not correctly locking the data, and you have race conditions in your code, making ColdFusion trying to access data that you have told it is there, but could subsequently have been changed. This is due to your code, not a shortcoming in ColdFusion.

Attributes scope vs attributes structure

Custom tags have an attributes scope. Cool.
I've also seen some other apps (and possibly ColdBox?) where the developer put everything into an attributes structure. For example in login.cfm:
<cfparam name="attributes.username" default="some value">
Is there a point to this besides having to specify attributes.foo which does improve readability, I'll admit but why reuse a name of a full scope?
Is this personal preference or am I missing something profound with the attributes scope?
It's nothing profound. A lot of frameworks (and individual developers) like to combine the form and url scopes into a single "event" object or something (ala your "attributes" example), but it doesn't really buy you much.
That said, naming a new object after an existing scope is misguided, and I'd recommend against it. What happens when you want something out of the attributes scope, not the attributes object?
You could always reference the object via variables.attributes.foo for explicitness, but that's a pain and a bit ugly. And of course, nothing stops you from accessing the attributes scope (scope priority would check attributes before variables.attributes), but then the person that has to read the code after you is more confused. It's essentially created a problem instead of solving one.
In Fusebox, the idea was that a individual file could be used as either a part of the framework, or it could be used as part of cfmodule. Inside of corefiles/application.cfc is:
...
<cfparam name="variables.attributes" default="#structNew()#" />
<cfif isDefined("URL")>
<cfset structAppend(attributes,URL,true) />
</cfif>
<cfif isDefined("form")>
<cfset structAppend(attributes,form,true) />
</cfif>
...
See GitHub for details

coldfusion making better use of cfparam

In our index files, at the top of the file we will generally <cfparam> out the variables that will come from the URL, form or wherever. However, we are getting a lot of bots hitting us with things like www.example.com/survey/index.cfm?nPageNumber=-1 meaning a cfparam like this:
<cfparam name="request.parameters.nPageNumber" default="1" type="numeric" />
will fail due to the nonsense a bot is putting into the querystring.
I find myself increasingly having to write my cfparams like this:
<cfif structKeyExists(request.parameters,"nPageNumber") AND isNumeric(request.parameters.nPageNumber)>
<cfparam name="request.parameters.nPageNumber" default="1" type="numeric" />
<cfelse>
<cfset request.parameters.nPageNumber = 1>
</cfif>
While this solves the issue, I can't help but feel this solution is not the best/most efficient. Am I using cfparam correctly or are there better ways of doing this?
Ensuring the existence of a variable, and validating its value are two separate tasks.
In the case of URL and Form your existence code should be something like:
<cfparam name="URL.nPageNumber" default="1" type="string">
The use of type there is just to ensure that nothing truly bizarre has happened such as the value is a struct or query, etc. You don't want to get specific at this point since you want a graceful error and not at 500 for the user.
Once you've made sure that the value exists, you then need to validate the value.
<cfif isNumeric(URL.nPageNumber) EQ false OR URL.nPageNumber LT 1 OR URL.nPageNumber GT Variables.MaxPages>
<cfset ArrayAppend(Variables.ErrorArray, "Incorrect page number requested.")>
</cfif>
You could force the value to something sane, but see Martian Headsets for a counter argument to the robustness principle.
Providing an error message instead of "displaying something sane" will inform your users that they are doing something wrong, and means you're not forced to use canonical urls if you're not already (although you should be).
Yes, it's more work. You can devise some abstraction for it all, but at the raw level, that's what you should be doing with your cfparams and validation.
In the situation where you don't need to have a friendly response, such as a bot or a request that is obviously a hack or probing, there's the additional option to serve a "400" response code. The w3c defines the response as "The request had bad syntax or was inherently impossible to be satisfied." here and "The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications." here.