Rethrow in cfscript?

ColdFusion MX added try/catch to the CFSCRIPT, a welcome addition, but you can't throw an exception, or rethrow. Doing a throw is quite easy if you write a UDF for it. However, rethrow is not so easy. You may think:

<cffunction name="rethrow">
<cfrethrow>
</cffunction>

However, this will cause a syntax error since rethrow must be contained inside a cfcatch block. For the heck of it, I tried the following:

<cffunction name="rethrow">
   <cftry>
      <cfcatch>
      <cfrethrow>
      </cfcatch>
   </cftry>
</cffunction>

<cftry>
   <cfscript>
      try {
         throw("my type","my ex");
         } catch(Exception e) {
            rethrow();
         }
         
   </cfscript>
   <cfcatch>
      <cfoutput>exception thrown</cfoutput>
      <cfdump var="#cfcatch#">
   </cfcatch>
</cftry>

What surprised me is that my rethrow UDF noticed an error had occured and automatically entered the cfcatch block.

This had one problem though. I could call rethrow outside of cfcatch. It wouldn't throw an exception, it would simply do nothing. I modified the UDF like so:

<cffunction name="rethrow">
   <cftry>
      <cfcatch>
      <cfrethrow>
      </cfcatch>
   </cftry>
   <cfthrow type="Context validation error" message="Context validation error for CFRETHROW.">
</cffunction>

You will only get to the end of the UDF when you haven't called rethrow() in a catch block.

p.s. Normally I'd add returnType/output/etc to my code. Don't forget to do so if you actually use the UDFs.

p.s.s. And of course, I'd much prefer it if MACR would simply add throw/rethrow to cfscript. :)

Archived Comments

Comment 1 by Ivo D. Silva posted on 3/9/2004 at 9:22 PM

"p.s.s. And of course, I'd much prefer it if MACR would simply add throw/rethrow to cfscript. :)"

I would prefer a full cfscript implementation of cfml tags.

Sure tag based syntax is good, and i love it, but for the presentation layer ... i really would prefer a script based syntax for the business layer ( much like the Flex programming model ).

Next xmas i'll send this gift request to santa ..

Please please macromedia, give cf a nice programming model like his brother flex !

Comment 2 by Eli Gordon posted on 11/2/2004 at 10:52 AM

One thing that should be clarified is that this rethrow() function needs to be called within a CFTRY block--simply being within a cfscript try{} block isn't enough.
For example, the following code will not work (rethrow() throws a "Context validation error"):
&lt;pre&gt;
&lt;cfscript&gt;
try {
try {
throw('foo', 'bar');
} catch (foo e) {
rethrow(); // error here
}
WriteOutput("rethrow() didn't work");
} catch (foo e) {
WriteOutput("rethrow() worked");
}
&lt;cfscript&gt;
&lt;/pre&gt;
While the following code does work:
&lt;pre&gt;
&lt;cftry&gt;
&lt;cfscript&gt;
try {
throw('foo', 'bar');
} catch (foo e) {
rethrow();
}
WriteOutput("rethrow() didn't work");
&lt;/cfscript&gt;
&lt;cfcatch type="foo"&gt;
&lt;cfoutput "rethrow() worked"&gt;
&lt;/cftry&gt;
&lt;/pre&gt;

Comment 3 by Eli Gordon posted on 11/2/2004 at 10:57 AM

That sure did look ugly... Let's try that comment again:
----------

One thing that should be clarified is that this rethrow() function needs to be called within a CFTRY block--simply being within a cfscript try{} block isn't enough.

For example, the following code will not work (rethrow() throws a "Context validation error"):

&lt;cfscript&gt;

try {

try {

throw('foo', 'bar');

} catch (foo e) {

rethrow(); // error here

}

WriteOutput("rethrow() didn't work");

} catch (foo e) {

WriteOutput("rethrow() worked");

}

&lt;cfscript&gt;

While the following code does work:

&lt;cftry&gt;

&lt;cfscript&gt;

try {

throw('foo', 'bar');

} catch (foo e) {

rethrow(); }

WriteOutput("rethrow() didn't work");

&lt;/cfscript&gt;

&lt;cfcatch type="foo"&gt;

&lt;cfoutput "rethrow() worked"&gt;

&lt;/cftry&gt;

Comment 4 by Michael Benoit posted on 3/16/2006 at 2:55 AM

Sorry for necroposting...

I was disappointed that throw() and rethrow() weren't included in the CF MX updater 7.01.

Here are my versions of throw() and rethrow():

<cfcomponent displayname="allErrorHandling">
<cffunction name="throw" access="public" returntype="void" hint="Call throw() with named arguments, rather than positional. While all arguments are optional, the message and detail argments are strongly recommended. The object paramter of CFTHROW is not supported.">
<cfargument name="message" type="string" required="false" default="">
<cfargument name="detail" type="string" required="false" default="">
<cfargument name="errorcode" type="string" required="false" default="">
<cfargument name="extendedinfo" type="string" required="false" default="">
<cfargument name="type" type="string" required="false">
<cfif StructKeyExists(arguments, "object")>
<cfthrow detail="#arguments.detail#" errorcode="#arguments.errorcode#" extendedinfo="#arguments.extendedinfo#" message="#arguments.message#" type="#arguments.type#">
<cfelse>
<cfthrow detail="#arguments.detail#" errorcode="#arguments.errorcode#" extendedinfo="#arguments.extendedinfo#" message="#arguments.message#">
</cfif>
</cffunction>
<cffunction name="rethrow" access="public" returntype="void" hint="Use this only inside catch blocks in CFSCRIPT. Unlike CFRETHROW, you must feed in the exception being rethrown. Only the message, detail, errorcode, extendedinfo, and type keys of the exception structure will be rethrown, but it's better than nothing.">
<cfargument name="exception" type="struct" required="yes" hint="Any exception structure from a catch block in CFSCRIPT.">
<cfscript>
if (not StructKeyExists(exception, "message")) {
exception["message"] = "";
}
if (not StructKeyExists(exception, "detail")) {
exception["detail"] = "";
}
if (not StructKeyExists(exception, "errorcode")) {
exception["errorcode"] = "";
}
if (not StructKeyExists(exception, "extendedinfo")) {
exception["extendedinfo"] = "";
}

if (StructKeyExists(exception, "type")) {
throw(exception.message, exception.detail, exception.errorcode, exception.extendedinfo, exception.type);
} else {
throw(exception.message, exception.detail, exception.errorcode, exception.extendedinfo);
}
</cfscript>
</cffunction>
</cfcomponent>

Comment 5 by Charlie Arehart posted on 8/16/2006 at 7:49 AM

Ray, I notice you haven't added this to cflib. Is there something missing that's caused that? I'm doing an article in the CFDJ on error handling and am pointing to your throw UDF. If you might be adding this one, I'd point to it also.

Comment 6 by Raymond Camden posted on 8/16/2006 at 2:44 PM
Comment 7 by Charlie Arehart posted on 8/17/2006 at 7:04 AM

Great, thanks, and duly noted in the article. Cheers.

Comment 8 by Adam Lehman posted on 5/16/2009 at 7:15 AM

Done... ColdFusion 9 has throw/rethrow in CFSCRIPT. Booyah!

Comment 9 by Adam Lehman posted on 5/16/2009 at 7:18 AM

Ps. You're welcome. ;-)

Comment 10 by Zach Stevenson posted on 3/21/2011 at 8:11 PM

Call me crazy, but wouldn't the following work as a rethrow?

try
{
...
}
catch(Any e)
{
throw(ArgumentCollection = e);
}

Comment 11 by Raymond Camden posted on 3/21/2011 at 8:14 PM

Did you try it? ;)

Comment 12 by Zach Stevenson posted on 3/21/2011 at 8:20 PM

Just Tried it, didn't work.

However, putting:

Throw(object = e);

does rethrow your error.