tracker issue : CF-3546046

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

restSetResponse() requires the method to be returntype void

| View in Tracker

Status/Resolution/Reason: Closed/Fixed/

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

Created: 04/19/2013

Components: Documentation

Versions: 10.0

Failure Type:

Found In Build/Fixed In Build: Final / 287252

Priority/Frequency: Major / Some users will encounter

Locale/System: English / Windows 7 64-bit

Vote Count: 1

Listed in the version 2016.0.0.297996 Issues Fixed doc
Verification notes: verified_fixed on May 22, 2018 using build 2016.0.01.298513
snippet in the docs:

You must set the returntype attribute of the function to void when a custom response is returned using the function restSetResponse.

Note that it says no such thing against the docs for the actual function (which would be the most sensible place to mention it), just in this devnet article. I have annotated the docs to point this out.

The Stackoverflow question makes a good point:

It works well, except that it forces you to set the function's returntype to "void". The problem with "void" is that whenever I throw an exception, it no longer returns the proper JSON error message.
And they're right. It's entirely reasonable that a method might only conditionally furnish its response via this restSetRespose(), and otherwise respond by returning stuff (be it an error in this case, or any other sort of response). It makes no sense to me that whether or not restSetResponse() works is based on the return type of the method.


Refs:
http://adamcameroncoldfusion.blogspot.co.nz/2013/03/restsetresponse-requires-method-to-be.html
http://stackoverflow.com/questions/15711287/coldfusion-10-rest-api-how-to-set-status-code-201-without-restsetresponse

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

Watson Bug ID:	3546046

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

Attachments:

Comments:

When restSetResponse() is used in a function we are mandating that the return type of the function to be void because, if the function sets the response and at the same type has a return value then there is an ambiguity on the response that needs to be sent back to the client. If there a throw statement in the function, then ColdFusion should catch the exception and create the appropriate response.
Comment by HariKrishna K.
15599 | May 29, 2013 06:08:44 AM GMT
The function where RestSetResponse is used should still be void. But fixed the issue of throwing exception on a function where the return type is void. Now it will return good error message, instead of 500 iinternal server error. When the return type, is void, we will using a differnt dispatcher. CFVoidVoidDispatchProvider or CFVoidOutInvoker. Here were not handling the exceptions to create a mapped response. Now handling the exceptions in these dispatchers also.
Comment by Paul N.
15600 | December 05, 2013 10:27:51 AM GMT
Did you not see this bit of my summary, Paul: {quote} And they're right. It's entirely reasonable that a method might only conditionally furnish its response via this restSetRespose(), and otherwise respond by returning stuff (be it an error in this case, or any other sort of response). It makes no sense to me that whether or not restSetResponse() works is based on the return type of the method. {quote} The key bit is: {quote} It's entirely reasonable that a method might only conditionally furnish its response via this restSetRespose(), and otherwise respond by returning stuff {quote} As for this comment Hair made: {quote} if the function sets the response and at the same type has a return value then there is an ambiguity on the response that needs to be sent back to the client. {quote} OK, well in the event that BOTH a return value and restSetResponse() are used, the throw an exception, or just pick one that takes precedence. Don't invent one-off rules that really make little sense in the bigger scheme of CFML. No other function requires a specific return type on a function for it to even work. It's not sensible that this one does. Simply deal with the issue IF IT BECOMES AN ISSUE. -- Adam
Comment by External U.
15601 | December 05, 2013 10:36:44 AM GMT
Sorry, perhaps this bit wasn't as clear as I could make it: {quote} OK, well in the event that BOTH a return value and restSetResponse() are used, the throw an exception {quote} What I mean is don't predicate it on the returntype, predicate it on whether one tries to use bot restSetResponse() followed by a returned value. And do this at RUNTIME. IE: there should be no problem having both in the one function, provided only one of them is actually used for a given request. EG: if (condition){ restSetResponse() } else{ return something } That should be fine. -- Adam
Comment by External U.
15602 | December 05, 2013 10:39:08 AM GMT
RestSetResponse is not like return statement. RestSetResponse does not actually return anything. It just sets the custom response, which ColdFusion gets and sends the response. In ColdFusion, cffunctions should adhere to the return type. If you have specified a return type, you should return some value of that type. For eg. I have a CFC like, Test.cfc -------- <cfcomponent> <cffunction name="func1" access="public" returntype="Struct"> <cfargument name="retrunStruct" type="boolean"> <cfif retrunStruct eq TRUE> <cfreturn {key:"Value"}> <cfelse> <!--- Not returning anything. ---> </cfif> </cffunction> </cfcomponent> If I invoke the function like, <cfset a = CreateObject("component", "Test")> <cfset a.func1(true)> it will work fine. But if I invoke it like, <cfset a = CreateObject("component", "Test")> <cfset a.func1(false)> we will get an error. "The value returned from the func1 function is not of type Struct." In this case, you have to return an empty struct atleast. <cfcomponent> <cffunction name="func1" access="public" returntype="Struct"> <cfargument name="retrunStruct" type="boolean"> <cfif retrunStruct eq TRUE> <cfreturn {key:"Value"}> <cfelse> <cfreturn {}> </cfif> </cffunction> </cfcomponent> It is the same case as RestSetResponse(). Even if you are using RestSetResponse to set a Custom Response, you have to return an empty Struct, if you have specified the return type as struct. if (condition){ restSetResponse() return something } else{ return something } So you will sending both (custom response and an empty struct, in this case). This is why it is ambiguos to use RestSetResponse in a function which has a non void return type. We have 2 options. The first is make the returnType as void to use RestSetResponse(current behaviour, the exceptions thrown are handled correctly.). The other option is you can specify a non void returnType. But you have to return a value of correct return type. The ColdFusion will not throw error, but will ignore the return value and use the response set using the RestSetResponse.
Comment by Paul N.
15603 | January 03, 2014 07:55:45 AM GMT
And what if the return type is ANY or STRING, Paul? It is completely legit to not return anything (indeed not have a return statement) in these situations. In fact it's just ColdFusion's abject incapability to not "get" null which prevents any returntype from not working this way (NULL is an OK returntype for any or string, but not OK for struct or numerics because ColdFusion is a bit rubbish). Still: the various areas in which ColdFusion is already rubbish oughtn't be increased to cover this situation as well. What you SHOULD be doing here is fixing the rest of CF so that it's actually uniformly capable of dealing with null return values. But anyway... I think you have made at least HALF a case here. I think your approach is exacerbating an already poor situation, but I don't think it's intrinsically wrong any more. It's certainly not *right* either though. -- Adam
Comment by External U.
15604 | February 27, 2014 10:47:59 PM GMT
Sorry, but I think I've determined a reasonable situation in which the way this currently works is not fit for purpose. The long version is here: http://cfmlblog.adamcameron.me/2014/04/coldfusion-rest-services-and.html The short version is that GET methods (which need to return something), quite legitimately also need to NOT return anything if they're not found, ie: a 404 situation. This is just how REST works. It might conflict with how "normal" methods in CFML work, but so be it: REST responses need to work differently. So we need to be able to use restSetResponse() on methods that might normally return something, but don't. This is probably less a revision to restSetResponse(), and more a revision to how function-returns work in a REST situation though. You need to accept that a NULL return is still legit for any given data type. -- Adam
Comment by External U.
15605 | April 20, 2014 11:59:39 AM GMT
Hello?
Comment by External U.
15606 | February 15, 2015 04:48:01 PM GMT
Hi Paul, +1 to your second suggestion: -------------------------------------------- The other option is you can specify a non void returnType. But you have to return a value of correct return type. The ColdFusion will not throw error, but will ignore the return value and use the response set using the RestSetResponse. -------------------------------------------- Basically: 1) allow RestSetResponse() in non-void function 2) require return value, but ignore it when RestSetResponse() is used So can your idea still be done? It seems it is the expected behavior and would resolve this ticket. Can this ticket please be re-opened/reconsidered based on your 2nd suggestion? Thanks!, -Aaron
Comment by External U.
15607 | December 01, 2015 10:36:35 PM GMT
Then, the doc could be updated from: ----------- Note: restSetResponse() can only be used on function with a return type of void. It will cause errors if it is used on functions that have any other return type. ----------- to something like: ----------- Note: ColdFusion will ignore the function's return value and use the response set using the RestSetResponse(). -----------
Comment by External U.
15608 | December 01, 2015 10:42:02 PM GMT
We would update the documentation for this.
Comment by Rupesh K.
15609 | December 10, 2015 11:24:46 PM GMT
Hi Rupesh, I'm not sure what exactly you mean.. Do you mean Paul's idea can't be done?: Paul's comment from 5:25:45 AM GMT+00:00 Jan 3, 2014 -------------------------------------------- The other option is you can specify a non void returnType. But you have to return a value of correct return type. The ColdFusion will not throw error, but will ignore the return value and use the response set using the RestSetResponse. -------------------------------------------- That's a good idea and would solve the issue. Thanks!, -Aaron
Comment by External U.
15610 | December 11, 2015 04:49:01 AM GMT
Hi Rupesh, What will be documented? Can Paul's idea be done? It's reasonable: Paul's comment from 5:25:45 AM GMT+00:00 Jan 3, 2014 -------------------------------------------- The other option is you can specify a non void returnType. But you have to return a value of correct return type. The ColdFusion will not throw error, but will ignore the return value and use the response set using the RestSetResponse. -------------------------------------------- Thanks!, -Aaron
Comment by External U.
15611 | December 11, 2015 06:01:06 PM GMT
*bump*
Comment by External U.
15612 | January 05, 2016 01:05:47 AM GMT
*bump* Adobe, I got an email that this ticket was updated. I do not see your answer to the following question: Can Paul's idea (below) be done: ============================================ Paul's comment from 5:25:45 AM GMT+00:00 Jan 3, 2014 -------------------------------------------- The other option is you can specify a non void returnType. But you have to return a value of correct return type. The ColdFusion will not throw error, but will ignore the return value and use the response set using the RestSetResponse. -------------------------------------------- ============================================ Thanks!, -Aaron
Comment by External U.
15613 | January 25, 2016 01:04:47 AM GMT
Hi Aaron, The documentation is not made live yet. I have updated the team to make it live and update it here.
Comment by HariKrishna K.
15614 | January 25, 2016 01:28:38 AM GMT
Hi Aaron, Here is the link to the live doc: https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-m-r/restsetresponse.html Thanks a lot for your help.
Comment by Saurav G.
15615 | January 25, 2016 01:58:01 AM GMT
Hi Hari, Thank you for the follow-up. There were 2 items discussed: 1) possibility to allow non-void return type, per Paul's suggestion 2) updating the docs My question is about #1. I am wondering if Paul's suggestion can be done as part of this ticket. Thanks!, -Aaron
Comment by External U.
15616 | January 25, 2016 02:02:23 AM GMT
Sorry about the double-post. A ColdFusion timeout exception was thrown when I tried to post my comment.
Comment by External U.
15617 | January 25, 2016 02:09:14 AM GMT
Hi Saurav and Hari, Thanks very much for the doc update. I see the doc update implies the containing UDF's return type can now be non-void. Awesome. That answers my question. Thanks very much!, -Aaron
Comment by External U.
15618 | January 25, 2016 02:11:01 AM GMT
Was this fix supposed to have been made public in a ColdFusion 10 update already? I have just tried with CF 10 update 21. The response I set with restSetResponse() is still being ignored unless the return type of the function is void. Can anyone verify whether they can actually use restSetResponse with a non-void function? If it's not supposed to be public yet, when will this fix be released?
Comment by External U.
15619 | November 01, 2016 12:07:36 PM GMT
Need to use restSetResponse with non-void function
Vote by External U.
15622 | November 01, 2016 12:07:55 PM GMT
Hi all, This ticket was not fixed. RestSetResponse() still requires the method to be returntype void, otherwise it is ignored. All Adobe did to -fix- the ticket was: 1) allow the CFThrowErrorCode-to-HTTPResponseCode conversion magic to also work in returntype void functions and 2) add "Note: ColdFusion ignores the function's return value and uses the response set using the RestSetResponse() function." to the RestSetResponse() doc. To illustrate, imagine you have a function that returns a query. And, when there are 0 records to return, you want the REST response code to be 404. RestSetResponse() fits the bill, except it cannot be used in a function that returns non-void. So, Adobe says to use cfthrow(type="RestError", errorcode=404). And CF automagically converts 404 exception code to a 404 HTTP code. And this works okay, until you call the function directly (i.e. invoke()) and an exception is thrown instead of returning a 0-row query. IMHO, CF-3546046 should be re-opened and fixed such that the fix matches the edit they made to RestSetResponse() doc. Meaning, RestSetResponse() should ignore the function's return value and use the response set using the RestSetResponse() function. Just make the behavior match the doc. And if the function isn't called via REST, then RestSetResponse() is ignored. Thanks!, -Aaron
Comment by Aaron N.
15620 | February 01, 2017 07:20:52 AM GMT
I've filed CF-4198298 to get this issue fixed, just in case CF-3546046 isn't re-opened. Thanks!, -Aaron
Comment by Aaron N.
15621 | February 01, 2017 07:34:00 AM GMT
Summary: Initially: 1) In non-void UDF, restSetResponse() was ignored 2) In void UDF, cfthrow returned custom REST response as HTML of error handler page (instead of JSON) Both were filed as CF-3546046, but only #2 was fixed (which I've verified in CF2016 Update 1). #1 was re-filed as CF-4198298. In Aether Public Beta Update 1, #1 is fixed but #2's fix was reverted/undone/unfixed. Filed CF-4202547 to re-fix #2. Thanks!, -Aaron
Comment by Aaron N.
27906 | May 22, 2018 07:31:44 AM GMT