Tuesday, March 16, 2010

Be careful when using try/catch inside of a cftransaction tag.

While doing development on a somewhat large project for managing weatherization jobs I found a funny little thing about using the cftransaction tag outside of a try/catch statement. Take the chunk of code below for example:

<cftransaction>
<cfscript>
try
{
variables.LocationCodeDataDelegate.UpdateLocationCode(arguments.LocationCodeView.GetLocationCode());
arguments.Event.AddMessage("Location code updated successfully.");
arguments.Event.SetError(false);

}
catch(any ex)
{
arguments.Event.SetError(true);
arguments.Event.AddMessage("There was an error updating the location code.<br><br>#ex.message# The error occured on or around line #ex.TagContext[1].line# on file #ex.TagContext[1].template#<br>#ex.detail#",true);
}
</cfscript>
</cftransaction>

Now I had incorrectly assumed that if my UpdateLocationCode function would throw an error that the transaction would be rolled back automatically. It turns out that since that error is caught and normal processing continues after the catch tag that this transaction commits just fine.

The fix for this problem is a simple one. In my Event object I have a boolean property called Error that is defaulted to true, only when the code inside my try block completes is it set to false. All I need to do is check my Event object for an error condition right before my tag and rollback the transaction if the error condition is true as shown below:

<cftransaction>
<cfscript>
try
{
variables.LocationCodeDataDelegate.UpdateLocationCode(arguments.LocationCodeView.GetLocationCode());
arguments.Event.AddMessage("Location code updated successfully.");
arguments.Event.SetError(false);
}
catch(any ex)
{
arguments.Event.SetError(true);
arguments.Event.AddMessage("There was an error getting the location code.<br><br>#ex.message# The error occured on or around line #ex.TagContext[1].line# on file #ex.TagContext[1].template#<br>#ex.detail#",true);
}
</cfscript>
<cfif arguments.Event.GetError()>
<cftransaction action="rollback" />
</cfif>
</cftransaction>
Fork me on GitHub