Copy link to clipboard
Copied
Hi all,
So we use the onError function in Application.cfc to show users a generic message if they happen to encounter an error. In our development environments, we generally comment out the onError function which results in errors producing a very nice helpful stack trace.
This has proved problematic in the event of changing the Application.cfc and forgetting that you did that, resulting in an unwanted change to prod. Ideally it should be caught but that's not the point. And it'd be nice if nobody had to worry about it.
I'd like to know if there's any way to show that nice stack trace screen if we are in a development environment. Assuming I know that we are in a dev environment, I've tried wrapping the entire onError function in a <cfif> but it doesn't seem to care about that. Is there a template somewhere that I can invoke that presumably takes the Exception variable and puts it in the nice stack trace format? Dumping the Exception variable is alright but not nearly as legible.
Thanks!
Copy link to clipboard
Copied
Lots to chew on there, Joey. And this is the kind of question that could raise many opinions, since there's no hard-and-fast solution to what you are seeking. I do have a suggestion for you, though.
Let me say first that someone will almost surely suggest that "you can fix this by putting the IP addresses of your development machines in the 'debug ip address' settings of the CF Admin". While that is indeed something one can do, note that it affects ONLY the debugging output. It does NOT control the error display.
Second, you refer to the "nice stack trace" you see in the error, and the display of that (if you do NOT handle an error) is controlled by a setting on the "debug output settings" page called "robust exception handling". If that's enabled, one WILL see that detail, assuming an error is NOT handled (and again REGARDLESS of whether one is on the "debug ip address" list or not.)
Third, someone may want to point out that you can print out a stack trace in CFML using a new function introduced in CF10, called callstackdump(). But I don't think that's the solution for you here.
In fact, something else one could do in such an error handler is use cftrethrow (within an onerror method, or within cfcatch, or if using script, use simply rethrow within a catch), and that will "throw the error up to the next error handler" (after whatever you do in your error handler). And if there WAS NO error handler "above", then it would dump on screen the classic error page that you seem to want.
But all those 3 options do require that you programatically "detect" that you are "in development" and "want to see the error details, rather than have them 'handled' by your error handler". And you are acknowledging that you don't want code that "has to change" based on whether you are in dev or not, which is wise for the reason you mention.
But unfortuantely, there's no built-in mechanism in CF that "detects whether you are in dev or prod". So what most people do in your situation is simply have a variable that they set which tracks that. They may set it in the application.cfc/cfm, or maybe as an environment variable in the OS or Java (which can be accessed via the CGI scope in later versions of CF), or maybe store it in a database (under the presumption that the dev env points to a dev db and prod points to a prod one), and so on.
Some have their code "detect" what "version" is running based on the URL used, which is very risky if you ever setup a hosts file to "simulate a prod request in dev".
Bottom line, this is an interesting challenge. And if anything, if you can come up with SOME way to detect "which version you're running" that DOES work for you (or go with setting a variable), at least you could then use THAT in the onerror function to decide what to do.
And you talked about wrapping the onerror method of application.cfc itself in an if. I'd not do that. I'd do the condition check WITHIN the method. And recall above how I said you could rethrow/cfrethrow the error "if you're in test" (and at that point, you could have either let it do other logging/emailing of the error).
The only gotcha here is that if you have a "site-wide error handler" defined in the CF Admin, then THAT would catch the rethrow from the onerror method, and do whatever IT is supposed to do. So you could add similar logic to THAT.
Or you could change what the CF Admin points to for that "site-wide error handler" (on the first "settings" page of the Admin), whether to point to a different FILE in dev vs prod, or the same file but which is DIFFERENT in prod vs test, or in fact you could leave OFF any file in test. That would again mean that any lower-level error that was NOT handled would just "dump on the screen" (with the amount of detail controlled by that "robust exception handling" setting also in the admin).
Finally, there have even been CFML error handling frameworks (and non-CFML ones) that people have used, which embue a lot of this sort of capability (and more), which may be worth considering. I point to them here: https://www.cf411.com/error
So there are some ideas. Let us know if this gets you going, or perhaps prompts new questions.
Copy link to clipboard
Copied
2 suggestions, each vital:
1) Use a version control system to distinguish your development code from your production code.
2) Ensure that no two ColdFusion applications in your environment share the same name. I am of course referring to the name property in Application.cfc.
Best practice is to use a distinct Application.cfc for each application. Adopt a custom similar to the following:
<cfcomponent>
<cfset this.name = "customerDev">
</cfcomponent>
<cfcomponent>
<cfset this.name = "customerTest">
</cfcomponent>
<cfcomponent>
<cfset this.name = "customerProd">
</cfcomponent>
respectively, for code in the Development, Test and Production environments. You could then choose in which of the Application files to omit the onError event-handler.