tracker issue : CF-3971067

select a category, or use search below
(searches all categories and all time range)
Title:

keyExists member function not available on all struct objects

| View in Tracker

Status/Resolution/Reason: Closed/Fixed/

Reporter/Name(from Bugbase): Adam Tuttle / Adam Tuttle (Adam Tuttle)

Created: 04/16/2015

Components: Language

Versions: 11.0

Failure Type: Non Functioning

Found In Build/Fixed In Build: CF11_Final /

Priority/Frequency: Critical / All users will encounter

Locale/System: ALL / Platforms All

Vote Count: 3

Listed in the version 2016.0.0.297996 Issues Fixed doc
Verification notes: verified_fixed on August 24, 2019 using build 2016.0.01.298513
Related Bugs:
CF-3976479 - Similar to


Problem Description:

The exception object available in a cfcatch / onError function doesn't support the keyExists member function. I would imagine there are other "special" structs that also don't get the struct member functions because they weren't created with {} or structNew(), but I haven't found them yet.


Steps to Reproduce:

<cfscript>
	try {
		throw(message="test throw");
	}catch( any e ){
		writeOutput("e.keyExists('message')=#e.keyExists('message')#");
	}
</cfscript>


Actual Result:

"The keyExists method was not found"


Expected Result:

e.keyExists('message')=test throw
(all structures should support all struct member functions)


Any Workarounds:

use structKeyExists()

----------------------------- Additional Watson Details -----------------------------

Watson Bug ID:	3971067

External Customer Info:
External Company:  
External Customer Name: Adam
External Customer Email:  
External Test Config: My Hardware and Environment details:



OSX 10.10.2

Apache 2.4.9

CF11u5 public

Attachments:

Comments:

+1 Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.Please explain in 25 characters or more how this bug impacts productivity and why you are adding a vote.
Vote by External U.
7864 | April 16, 2015 09:03:34 AM GMT
+1. “Chewy, we're home." - Han Solo, Star Wars VII (The Force Awakens)
Vote by External U.
7865 | April 16, 2015 05:33:49 PM GMT
While Calling structKeyExists(), Coldfusion explicitly convert an exceptopn object to Map. Same can't be done in for member function call. For member function, the object has to be an instance of Map object.
Comment by Awdhesh K.
7853 | August 18, 2015 07:40:28 AM GMT
I do not accept that response, Awdhesh. "It's hard" is not a valid excuse for doing something that will make the language better. Here, let me do part of your job for you: You write a KeyExists member function on your exception class that converts the exception to a map, then checks to see if the key exists.
Comment by External U.
7854 | August 18, 2015 08:16:32 AM GMT
Yeah that's a bullsh!t excuse, Awdhesh. don't convert anything, just implement the same struct interface on the exception class too. This is basic OO.
Comment by External U.
7855 | August 19, 2015 12:09:49 AM GMT
You got me wrong Adams. Let me clear the things in details. The structKeyExists function work as top-to-bottom approach. The first thing known to the system the function name "StructKeyExists" and whereever system encounters this, it tries to convert the object blindly to Map instance. In this work flow, the exception is not a Map interface as you have assumed, rather it is forcefully done at demand through an utility function, otherwise there will be a big performance hit. Member function works as bottom-to-top approach. The first thing known to the system is the object type. Here system whether the passes object is one of the Member Function supported object type or not. If not (that is the case here), it will by-pass member function completely. To support it we will have to add a hack wherein exception object needs to added for this special case, which is not common and will cause some performance hit though the fix is technically easy.
Comment by Awdhesh K.
7856 | September 22, 2015 01:24:35 AM GMT
No, Awdhesh: I did not get you wrong. What's more, you didn't seem to read (or perhaps understand, although I suspect it's a case of simply not reading clearly) what either of us said. Furthermore, you don't seem to "get" how some basics of OO works, which is pretty worrying. I think perhaps you are out of your depth here, so it might be an idea to escalate it.
Comment by External U.
7857 | September 22, 2015 01:32:15 AM GMT
Awdhesh-I almost want to take a poll on this: "this special case, which is not common". I don't think it's quite as uncommon as you do. Many are currently using StructKeyExists on exceptions either within a framework or within their own code. As more people start taking advantage of member functions and refactoring code to replace usage of procedural BIFs, the expectation will be that keyExists will work on exception objects.
Comment by External U.
7858 | September 22, 2015 09:17:51 AM GMT
Further questions: If the exception object is not a "Map", what is it? What is the business reason for using a different object type for exceptions than other structures?
Comment by External U.
7859 | September 22, 2015 02:47:24 PM GMT
It's an Exception object, Carl. CF has a bunch of wrapper classes which ultimately extend java.lang.Exception. This is the correct approach to take here IMO: the things are exceptions, not structs. However... there's absolutely no reason - given Adobe have already decided one can treat one of their exceptions as if it was a struct when using procedural functions - for them to implement the struct "interface" on their coldfusion,runtime.NeoException class. There's no need to coerce the thing into being a map; just implement the struct interface's methods in coldfusion,runtime.NeoException. I use the term "interface" loosely here cos it seems Adobe haven't used interfaces to express their OO contracts, but I mean "implement methods of the same name and same functionality as a struct has, on the NeoException class". The API you implement for these things needs to be uniform, Adobe. If structKeyExists() can take an Exception, then an Exception needs to also have a keyExists() method. CF shouldn't be coercing the types here; structKeyExists() should take an argument that is an implementation of SomeInterfaceWhichDefinesAStructsBehaviour (and both Structs and Exceptions and *anything else* can implement that interface), and that interface calls for a keyExists() method, which structKeyExists() actually calls on the relevant object.
Comment by External U.
7860 | September 22, 2015 04:36:35 PM GMT
Thanks for explaining that Adam. I'm not that familiar with the underlying Java plumbing, so I appreciate the insights.
Comment by External U.
7861 | September 22, 2015 07:57:11 PM GMT
+1 - yeah, that's a gotcha. Struct member functions should be available on all structs.
Vote by External U.
7866 | September 23, 2015 12:19:39 AM GMT
Hi Awdhesh, User expectation is that struct member functions are available on any struct. So it's that expectation that should be catered to. Thanks!, -Aaron
Comment by External U.
7862 | September 23, 2015 12:21:10 AM GMT
Adam, As explainded earlier, an exception object doesn't implement a struct interface as you pointed out. This can be verified by callling IsStruct(exceptionObj); When invoked, the above code will return you false for exception object. Just to clarify our current implementation, an exception object is dynamically converted to Map when structKeyExists function is encountered, not in the beginning by virtue of OOPs, as you have assumed. Though supporting it is not very technically challenging, but wanted to be sure not to add some workaround for an uncommon cases. Now as I got the sense that "keyexists" is quite common scenario, I will be adding this functionality soon.
Comment by Awdhesh K.
7863 | September 23, 2015 02:33:42 AM GMT
Hi Adobe, I've verified this is fixed in CF2016 Update 1 (build 2016.0.01.298513). Thanks!, -Aaron
Comment by Aaron N.
31178 | August 24, 2019 08:34:34 AM GMT