0
votes

With ColdFusion 9, I've created a component to work as a SOAP web service for a WinForm app I'm working on. When I call a remote function that returns a custom component via SOAP, none of the data is returned. I have a work around were I serializing to Json string in another method and deserializing in the client application. I would like to avoid this step. Is there an argument in the component / function I'm missing, or is this a bug in CF9?

I have yet to try other versions of ColdFusion. I have ran the same code on Railo and I get the data as intended.

When I view the method via a web browser I see the data returned in the selected returnformat.

Browser Returns:

{"stringField":"Test Value","dateField":"September, 29 2014 15:35:16"}

SoapUI Returns:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Body>
      <ns1:getComplexDataObjResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://complexdataservice">
         <getComplexDataObjReturn xsi:type="ns1:ComplexData">
            <dateField xsi:type="xsd:dateTime" xsi:nil="true"/>
            <stringField xsi:type="xsd:string" xsi:nil="true"/>
         </getComplexDataObjReturn>
      </ns1:getComplexDataObjResponse>
   </soapenv:Body>
</soapenv:Envelope>

testService.cfc

<cfcomponent output="false">

    <cffunction name="getComplexData" access="remote" output="false" returntype="String" hint="temporary workaround">
        <cfreturn serializejson(getComplexDataObj()) />
    </cffunction>

    <cffunction name="getComplexDataObj" access="remote" output="false" returnformat="json" returntype="complexData">
        <cfreturn new complexData("Test Value", Now()) />
    </cffunction>

</cfcomponent>

complexData.cfc

<cfcomponent output="false">

    <cfproperty name="stringField" type="string" />
    <cfproperty name="dateField" type="date" />

    <cffunction name="init" access="public" output="false">
        <cfargument name="Field1" required="true" type="string">
        <cfargument name="Field2" required="true" type="date">
        <cfset stringField = arguments.Field1>
        <cfset dateField = arguments.Field2>
        <cfreturn />
    </cffunction>

</cfcomponent>

In Railo I get:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Body>
      <ns1:getComplexDataObjResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://complexDataService">
         <getComplexDataObjReturn href="#id0"/>
      </ns1:getComplexDataObjResponse>
      <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:complexDataService.complexData" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="http://rpc.xml.coldfusion">
      <dateField xsi:type="xsd:dateTime">2014-09-29T20:06:26.420Z</dateField>
         <stringField xsi:type="xsd:string">Test Value</stringField>
      </multiRef>
   </soapenv:Body>
</soapenv:Envelope>
2

2 Answers

0
votes

Not sure whether it is ColdFusion bug or .Net. I have been experiencing same issue. My work around was changing component style="document" instead of RPC.

0
votes

Well I figured out what ColdFusion was doing. What I found was that the SOAP serialization would only pull the components properties out of the this scope of the component and not out of the variables scope.

I reworked the component into the following format. Note that I copied only the string argument into the this scope. Also to keep matching JSON on the non-SOAP requests, I had to make sure to use struct notation on the this scope variable name. I'm still not sure if I will be reworking all my components and may continue to rely on additional function due to the accessors don't manipulate the data returned via the SOAP requests.

<cfcomponent output="false" accessors="true">

    <cfproperty name="stringField" type="string" required="true" />
    <cfproperty name="dateField" type="date" required="true"  />

    <cffunction name="init" access="public" output="false">
        <cfargument name="Field1" required="true" type="string">
        <cfargument name="Field2" required="true" type="date">
        <cfset setStringField(arguments.Field1)>
        <cfset setDateField(arguments.Field2)>
        <cfset this["StringField"] = getStringField()>
        <cfreturn />
    </cffunction>

</cfcomponent>

This gives me a SOAP packet with a null date time and the test string as entered in my getComplexDataObj function.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Body>
      <ns1:GetComplexDataObjResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://complexdataservice">
         <GetComplexDataObjReturn xsi:type="ns1:ComplexData">
            <dateField xsi:type="xsd:dateTime" xsi:nil="true"/>
            <stringField xsi:type="xsd:string">Test Value</stringField>
         </GetComplexDataObjReturn>
      </ns1:GetComplexDataObjResponse>
   </soapenv:Body>
</soapenv:Envelope>