tracker issue : CF-3864383

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

[ANeff] Bug for: <cfinvokeargument omit=""> has no "supported" script equivalent (tag-to-script conversion failure)

| View in Tracker

Status/Resolution/Reason: Closed/Withdrawn/NotABug

Reporter/Name(from Bugbase): Aaron Neff / Aaron Neff (Aaron Neff)

Created: 12/08/2014

Components: Web Services

Versions: 11.0

Failure Type: Non Functioning

Found In Build/Fixed In Build: CF11_Final /

Priority/Frequency: Major / Some users will encounter

Locale/System: ALL / Platforms All

Vote Count: 1

<cfinvokeargument> has no "supported" script equivalent, therefore nillable arguments cannot be passed to a web service using cfscript in a "supported" way.

Repro:

MyCFC.cfc
---------
component {remote string function myFunction(required string arg1, string arg2="b") {return ARGUMENTS.arg2;}}

index.cfm
---------
<!--- Tag version --->
<cfinvoke webservice="http://www.domain.com/MyCFC.cfc?wsdl" method="myFunction" returnvariable="myResult" arg1="a">
  <cfinvokeargument name="arg2" omit="yes">
</cfinvoke>
<cfdump var="#myResult#" /><!--- Returns b (good) --->
<!--- Script version --->
<cfscript>
  cfinvoke(webservice="http://www.domain.com/MyCFC.cfc?wsdl", method="myFunction", returnvariable="myResult", arg1="a") {
	  cfinvokeargument(name="arg2", omit=true);
  }
  writeDump(myResult);//Returns b (good)
</cfscript>

Both the tag and script versions work, but Adobe says the script version isn't "supported".  cfinvoke()/cfinvokeargument() should be "supported" (and, thus, #3863516 should be marked Closed/Fixed).

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

Watson Bug ID:	3864383

External Customer Info:
External Company:  
External Customer Name: itisdesign
External Customer Email:

Attachments:

Comments:

In this case you pass NULL for the argument. So your invoke would look like myResult = invoke(o, "myFunction", {arg1="a", arg2=javacast("null", "")});
Comment by Rupesh K.
9583 | December 09, 2014 12:29:58 AM GMT
Hi Rupesh, I do appreciate that undocumented tip, thanks! But there are still 2 issues: 1) invoke() doesn't support web services (filed as #CF-3864527) 2) your tip doesn't work for minOccurs="0" (<cfinvoke omit="true"> properly handles nillable="true" vs minOccurs="0" - which aren't the same thing) Can this ticket please be re-opened since I believe this ticket still holds true (<cfinvokeargument omit=""> has no "supported" script equivalent)? Thanks!, -Aaron
Comment by External U.
9584 | December 09, 2014 01:51:24 AM GMT
[subscribe] //////////////
Vote by External U.
9593 | December 09, 2014 03:23:45 AM GMT
It does support webservice. I have added an example in the docs - https://wikidocs.adobe.com/wiki/display/coldfusionen/Invoke. Do you have an example of service with minOccurs="0" which you are not able to invoke?
Comment by Rupesh K.
9585 | December 09, 2014 04:21:42 AM GMT
Hi Rupesh, When I made my comment, I was just going by what the docs say (or rather, what they don't say). The <cfinvokeargument> doc does not explain that omit="true" is essentially the workaround for value="#javaCast("null", "")#" (which throws exception: "It requires the attribute(s): VALUE.") And the createObject() doc also doesn't mention that javaCast("null", "") can be used for nillible arguments. And this blog article says "Unfortunately, the syntax to pass optional arguments as nulls does not exist for the tag CFOBJECT or the function createObject()." (so I believed it, as it is from a reputable source): http://www.talkingtree.com/blog/index.cfm/2006/7/12/cfinvokeargument-omit-attr And since invoke() doesn't properly support web services (I saw the example you added to the invoke() doc, but invoke("http://www.domain.com/?wsdl", ..) would be the _correct_ script-equivalent of cfinvoke's web service support), I thought it didn't support them at all. Since nillable defaults to false, I have confirmed that javaCast("null", "") does in fact omit the element from the request when minOccurs="0" (so it works, as you said). You know, it would've helped if the docs actually said what you were telling me. And it'd help if invoke("http://www.domain.com/?wsdl", ..) was implemented properly (<cfinvoke> accepts a web service URL, so invoke() should too). Thanks!, -Aaron
Comment by External U.
9586 | December 09, 2014 06:25:19 PM GMT
So that others can follow along.. Before invoke() was introduced, web services could be invoked in script like so: Example 1: <cfscript> obj = createObject("webservice", "http://somedomain/test.cfc?wsdl"); result = obj.foo(arg1="ColdFusion"); </cfscript> And here's the tag version: Example 2: <cfinvoke webservice="http://www.domain.com/MyCFC.cfc?wsdl" method="myFunction" returnvariable="myResult" foo="bar"> And here's the invoke() version: Example 3: <cfscript> obj = createObject("webservice", "http://somedomain/test.cfc?wsdl"); result = invoke(obj, "foo", {arg1="ColdFusion"});//more verbose than obj.foo(arg1="ColdFusion") </cfscript> Really!? Why even support web services in invoke() if it's more verbose and not done in the same manner as the tag that it's named after? <cfinvoke> offers these advantages: 1) invokes the web service _and_ calls the function in one go 2) offers cfinvokeargument, for conditionally-including arguments w/o needing to create a temporary argumentcollection variable invoke()'s syntax is more verbose than just calling functions on the web service object directly. Additionally, invoke() requires creation of an additional variable if one wants to conditionally include arguments. <cfinvoke> was an improvement over createObject() and invoke() just took a step back and is more verbose. cfinvoke()/cfinvokeargument() currently work and do the job right - but they're currently not "supported". I'm not asking Adobe to do any more work here. I'm just suggesting that those 2 tag-to-script functions should be supported.
Comment by External U.
9587 | December 09, 2014 06:56:55 PM GMT
The invoke() doc says: "Invokes a web service" That's incorrect and should be changed to: "Invokes a method on a web service object" Thus, it fails to do what <cfinvoke> can do regarding web services.
Comment by External U.
9588 | December 09, 2014 07:12:20 PM GMT
I don't agree with the argument here. Invoking web service obviously means invoking a method on it. The intention for invoke() is not to replicate cfinvoke tag. Its intention is to dynamically invoke method on an object which it does.
Comment by Rupesh K.
9589 | December 10, 2014 12:23:44 AM GMT
Btw, this support for invoke() has been around since ColdFusion 8. The two examples that you have shown here have always worked like this but they have two different purpose - The first one is a direct static invocation on the object and the second one is a dynamic invocation which is like "reflection" in Java. Both have their own usage and you use one or another depending on your requirement. The second one comes handy when you can't hardcode the method name and its argument in the code and you are getting all of that dynamically at runtime.
Comment by Rupesh K.
9590 | December 10, 2014 12:28:29 AM GMT
Hi Rupesh, I believe you meant invoke() was added in CF10? I do agree dynamic method names is handy. If invoke() hadn't been introduced in CF10, I doubt it would've been introduced in CF11 since cfinvoke() serves that purpose well. Thanks!, -Aaron
Comment by External U.
9591 | December 10, 2014 04:07:41 AM GMT
Yes, you are right. It was added in CF 10. My bad. However, invoke() function has a cleaner syntax than the generic tag syntax and IMO, it has all the functionality that you need.
Comment by Rupesh K.
9592 | December 10, 2014 04:20:13 AM GMT