Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

coldfusion variables within cftry do not persist

I have a <cftry outside of a <cfmail tag. Within the <cftry a variable x is set. The variable x does not survive past the </cftry> .

<cfoutput>
<cftry>
<cfmail

          from     = "[email protected]"  
          to       = "[email protected]"          
          password = "something"
          username = "[email protected]"     
          server   = "localhost"                            
          replyto  = "[email protected]"
          subject  = "try-catch"               
          type     = "html"   >   

  <cfset x = 'abc'>

  this is to test email
  </cfmail>
  success

  <cfcatch>
  <cfoutput> email failed </cfoutput>
  </cfcatch
</cftry>


<!--- there is no variable x --->
x is #x#
</cfoutput>

I would like to find some way to pick up the value of x after the end of the <cftry. I've tried setting it with diferrent scopes inside the <cftry

<cfset register.x = 'abc'>  or even
<cfset session.x = 'abc'>

But neither of those preserves x outside of the <cftry>. Can someone suggest a way to preserve x beyond the </cftry>?

like image 764
Betty Mock Avatar asked Dec 17 '22 17:12

Betty Mock


1 Answers

It looks like you have a misconception about exception handling. Code within try is only fully executed if there is no exception. As soon as an exception occurs within try, the execution is stopped and jumps to the catch.

Example 1

<cftry>

    <cfset x = "everything is ok">

    <cfcatch>
        <cfset x = "an exception occured">
    </cfcatch>
</cftry>

<cfoutput>#x#</cfoutput>

This will always output everything is ok, because the code within try can be executed without causing an exception.

Example 2

<cftry>

    <cfthrow message="I fail you!">

    <cfset x = "everything is ok">

    <cfcatch>
        <cfset x = "an exception occured">
    </cfcatch>
</cftry>

<cfoutput>#x#</cfoutput>

This will always output an exception occured, because the code within try is only executed to the point where an exception is thrown (we are doing it on purpose here with <cfthrow>).

Example 3

<cftry>

    <cfset x = "everything is ok">

    <cfthrow message="I fail you!">

    <cfcatch>
        <cfset x = "an exception occured">
    </cfcatch>
</cftry>

<cfoutput>#x#</cfoutput>

This will still output an exception occured. Although the <cfset x = "everything is ok"> statement was properly executed and set the variable x, we are still jumping to the catch due to throwing an exception.

Example 4 (this is your issue!)

<cftry>

    <cfthrow message="I fail you!">

    <cfset x = "everything is ok">

    <cfcatch>
        <!--- we are doing nothing --->
    </cfcatch>
</cftry>

<cfoutput>#x#</cfoutput>

This will throw a runtime error telling you that x is undefined. Why? Because the statement declaring x is never reached due to encountering an exception. And the catch doesn't introduce the variable either.

Long story short

Your <cfmail> is causing an exception and <cfset x = 'abc'> is never reached.

The Fix

Proper error handling means to meaningfullly handle caught exceptions. Don't <cfoutput> email failed </cfoutput> your way out of it and act like you don't care. Log the exception (there is <cflog> for that) and monitor it. For debugging purposes, you can use <cfrethrow> within <cfcatch> to keep the original exception instead of silently absorbing the real reason for the error.

like image 55
Alex Avatar answered Jan 05 '23 02:01

Alex