Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type of cfcatch in ColdFusion

I am simply using a cftry/cfcatch block for handling any exception. Take this simple exception:

<cftry>
  <cfset abc = 1/0>
  <cfcatch>
    <cfdump var="#cfcatch.getClass().getName()#">
    <cfdump var="#isStruct(cfcatch)#">
    <cfdump var="#isObject(cfcatch)#">
    <cfdump var="#structKeyExists(cfcatch, 'type')#">
  </cfcatch>
</cftry>

And the above code's output is like this:

coldfusion.runtime.DivideByZeroException 
NO 
YES 
YES

My question is:

Why structKeyExists is not throwing an error as cfcatch is not of type struct?

And on dumping cfcatch it seems like it is a struct.

Any suggestions.

like image 356
Beginner Avatar asked Jun 03 '15 11:06

Beginner


3 Answers

I think what is confusing you is that you need to remember that ColdFusion is a typeless language.

ColdFusion documentation on data types

Data types
ColdFusion is often referred to as typeless because you do not assign types to variables and ColdFusion does not associate a type with the variable name. However, the data that a variable represents does have a type, and the data type affects how ColdFusion evaluates an expression or function argument. ColdFusion can automatically convert many data types into others when it evaluates expressions. For simple data, such as numbers and strings, the data type is unimportant until the variable is used in an expression or as a function argument.
ColdFusion variable data belongs to one of the following type categories:

  • Simple One value. Can use directly in ColdFusion expressions. Include numbers, strings, Boolean values, and date-time values.
  • Binary Raw data, such as the contents of a GIF file or an executable program file.
  • Complex ** A container for data. Generally represent more than one value. ColdFusion built-in complex data types include arrays, structures, queries, and XML document objects. You cannot use a complex variable, such as an array, directly in a ColdFusion expression, but you can use simple data type elements of a complex variable in an expression. For example, with a one-dimensional array of numbers called myArray, you cannot use the expression myArray * 5. However, you could use an expression myArray3 * 5 to multiply the third element in the array by five.
  • Objects Complex constructs. Often encapsulate both data and functional operations. The following table lists the types of objects that ColdFusion can use, and identifies the chapters that describe how to use them:

So the code within the <cfcatch> block contains an object that can be referred to as a "structure". By default the name of that structure is cfcatch. You can override that name by specifying the name attribute within the <cfcatch> tag.

The easiest way to see everything that is available to you is to <cfdump> the entire structure within the <cfcatch> block.

<cfcatch>
    <cfdump var="#cfcatch#">
</cfcatch>

CFCatch documentation on cfcatch

The cfcatch variables provide the following exception information:
cfcatch variable        Content
cfcatch.type            Type: Exception type, as specified in cfcatch.
cfcatch.message         Message: Exceptions diagnostic message, if provided; otherwise, an empty string; in the cfcatch.message variable.
cfcatch.detail          Detailed message from the CFML interpreter or specified in a cfthrow tag. When the exception is generated by ColdFusion (and not cfthrow), the message can contain HTML formatting and can help determine which tag threw the exception.
cfcatch.tagcontext      An array of tag context structures, each representing one level of the active tag context at the time of the exception.
cfcatch.NativeErrorCode Applies to type = "database". Native error code associated with exception. Database drivers typically provide error codes to diagnose failing database operations. Default value is -1.
cfcatch.SQLState        Applies to type = "database". SQLState associated with exception. Database drivers typically provide error codes to help diagnose failing database operations. Default value is 1.
cfcatch.Sql             Applies to type = "database". The SQL statement sent to the data source.
cfcatch.queryError      Applies to type ="database". The error message as reported by the database driver.
cfcatch.where           Applies to type= "database". If the query uses the cfqueryparam tag, query parameter name-value pairs.
cfcatch.ErrNumber       Applies to type = "expression". Internal expression error > number.
cfcatch.MissingFileName Applies to type = "missingInclude". Name of file that could not be included.
cfcatch.LockName        Applies to type = "lock". Name of affected lock (if the lock is unnamed, the value is "anonymous").
cfcatch.LockOperation   Applies to type = "lock". Operation that failed (Timeout, Create Mutex, or Unknown).
cfcatch.ErrorCode       Applies to type = "custom". String error code.
cfcatch.ExtendedInfo    Applies to type = "application" and "custom". Custom error message; information that the default exception handler does not display.
like image 107
Miguel-F Avatar answered Feb 03 '23 23:02

Miguel-F


(Too long for comments..)

Adding to Miguel-F's comments about CF's "typelessness"... according to the documentation, IsStruct uses the following rules (emphasis mine):

Returns True, if variable is a ColdFusion structure or is a Java object that implements the java.lang.Map interface. The return value is False if the object in variable is a user-defined function (UDF).

CFCatch does not meet that criteria. Hence why IsStruct returns false.

If you dump the cfcatch object, and examine the class hierarchy, you will see it is actually implemented as a subclass of java.lang.Exception:

coldfusion.runtime.DivideByZeroException
coldfusion.runtime.ExpressionException
coldfusion.runtime.NeoException
java.lang.RuntimeException
java.lang.Exception
java.lang.Throwable
java.lang.Object 

... not coldfusion.runtime.struct ie CF structure:

coldfusion.runtime.Struct
coldfusion.util.FastHashtable
coldfusion.util.CaseInsensitiveMap
java.lang.Object 

So as Miguel-F said, though it can be used like a structure (as can most complex object), technically it is not a CF structure, which explains why IsStruct returns false.

As an aside, the reason you can access its properties using dot notation, like with CF structures, is probably because the cfcatch class uses the JavaBean pattern:

ColdFusion can automatically invoke get_PropertyName_() and set_PropertyName_(value) methods if a Java class conforms to the JavaBeans pattern. As a result, you can set or get the property by referencing it directly, without having to explicitly invoke a method.

So for example, you can access the "message" property of cfcatch using:

     cfcatch.message

.. instead of invoking its "getter" method for that property:

     cfcatch.getMessage()
like image 22
Leigh Avatar answered Feb 04 '23 00:02

Leigh


cfcatch object acts like a struct, but it is not one. This is a special case.

What you can do is make a duplicate of cfcatch object and try isStruct method on it, it will return true.

for example-

<cftry>
   <cfset abc = 1/0>
     <cfcatch>
       <cfset dup = duplicate(cfcatch)>           
       <cfdump var="#isStruct(dup)#">
       <cfdump var="#isStruct(cfcatch)#">
       <cfdump var="#isObject(cfcatch)#">
     </cfcatch>
</cftry>

The output would be like

YES
NO
YES
like image 29
Tushar Bhaware Avatar answered Feb 04 '23 00:02

Tushar Bhaware