ColdFusion 10.0  -  Bug 3546046

Created on Friday, April 19, 2013

Login for more options

Title

restSetResponse() requires the method to be returntype void

Description

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

Test Configuration

My Hardware and Environment details:

App Language(s) English
OS Language(s) English
Platform(s) Windows 7 64-bit
Browser(s)

Notes (6)

  • Adam Cameron.

    8:17:59 PM GMT+00:00 Feb 27, 2014

    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

  • Paul Nibin K J

    5:25:45 AM GMT+00:00 Jan 3, 2014

    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.

  • Adam Cameron.

    8:09:08 AM GMT+00:00 Dec 5, 2013

    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

  • Adam Cameron.

    8:06:44 AM GMT+00:00 Dec 5, 2013

    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

  • Paul Nibin K J

    7:57:51 AM GMT+00:00 Dec 5, 2013

    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.

  • Hari Krishna Kallae

    4:38:44 AM GMT+00:00 May 29, 2013

    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.

Duplicate ID
Reported By Adam Cameron.

Status

State Closed
Status Withdrawn
Reason AsDesigned

Importance

Priority 3-High
Frequency Some users will encounter
Failure Type Incorrectly Functioning
Product Area REST Services

Build

Found In Build Final
Fixed In Build 287252

Attachments (0)

No Files Attached

Votes (0)

Your session has expired! Click to login
Current form data will be preserved

Cancel