Ask Ben: CFTry / CFCatch Issues
Someone contacted me the other day with a Try / Catch error. They were having problems with ColdFusion interacting with an Anti-Virus software. The AV software was putting locks on uploaded files which was causing ColdFusion to error out when it tried to access them. The programmer tried to handle this by using a Try / Catch code block, but was still getting errors. This is the snippet of code that I was sent:
<cfscript>
try {
fileRead = createObject( "java","java.io.FileInputStream" );
fileRead.init( theFile );
} catch (Any e) {
errorCode = '99';
};
fileRead.close();
</cfscript>
This code was causing a "java.io.FileInputStream" error. The problem is quite subtle and has to do with the line:
fileRead.close();
If you look at the Try / Catch block you will see that the fileRead variable creation is in the Try / Catch, but the fileRead.close() command is outside of the Try / Catch. This means that even though the variable fileRead might not contain a valid File object (if that is where the error occurs), the close() method is called no matter what.
To fix this, all we had to do was move the fileRead.close() to inside of the Try / Catch code block:
<cfscript>
try {
fileRead = createObject( "java","java.io.FileInputStream" );
fileRead.init( theFile );
fileRead.close();
} catch (Any e) {
errorCode = '99';
};
</cfscript>
Now, the fileRead.close() command only gets run if the fileRead variable contains a valid, initialized Java File object.
Want to use code from this post? Check out the license.
Reader Comments
this is why we need a cffinally tag and finally inside cfscript.
Can you give an example of how it might be used? I don't see how it would add anything over the CFCatch tag itself?
fileRead = createObject( "java","java.io.FileInputStream" );
try {
fileRead.init( theFile );
} catch (Any, e) {
errorCode = '99';
} finally {
fileRead.close();
};
No matter what happens the object will always be closed. With the code you wrote, if the fileRead.init throw an error, it will never make it to the close statement because the exception will be raised. Using finally, the exception is raise, but the object is still close because the finally statement is always executed even if an exception is raised or not.
Why not just put the "finally" code after the Try / Catch block? This seems like it would accomplish the same thing?
If the catch clause did a rethrow, the finally would still be executed (which would not be true of code placed after the try/catch block).
Ahhh, interesting. I didn't think of that, thanks.
Tony,
I gave a try to this code inside a CFscript
} catch (Any e) {
errorCode = '99';
} finally {
fileRead.close();
};
But it returns a syntax error on the finally line.... Is 'finally' part of coldFusion scripting language ? or is it pure Java/javascript? or I still miss something.... :)
I think there should be no comma within the catch brackets
@BKBK,
Thanks, that was a typo. Removed.
What's available on the exception (e) ?
@CP,
The thrown exception has information about the message and detail of the error. It also has the tag context so you can see what template and which lines of code have been executed. And, if you are particularly lost, it should also have the Java stack trace from which you might be able to take little pieces of information.
I couldn't agree more with Tony.
We need a FINALLY option for Coldfusion. Java has it. .NET has it.
A CFFinally solution:
<cftry>
<!---- Do some work ---->
<cfcatch type="any">
</cfcatch>
</cftry>
<!--- <cffinally> --->
<!--- Do some clean up work --->
<!--- </cffinally> --->
<cfif IsDefined("cfcatch")>
<cfthrow object="#cfcatch#">
</cfif>
One thing to note is that if you encounter an exception during the clean up work you will end up loosing the original exception. You could place the cleanup code around a try catch and log the original exception before throwing the new one. Too bad you can't wrap exceptions around each other.
@Abc,
I like it. Cool example.