15 Replies Latest reply on Sep 23, 2011 9:46 AM by insuractive

    Consuming SOAP Web Services

    J_Tremain

      Ok I have a web service that I'm trying to consume in CF9. I'm able to hit the wsdl with SOAPUI and see the results. The results come back in XML format. It basically shows a list of rooms we use as meetings and show the times they are reserved. Here's the CF code I've written for it:

       

      <cfinvoke 

          webservice="http://dwc-dreiman-w7e/WSExchangeMeetingRooms/exchange.asmx?WSDL"

          method="FindResourceDetailForDay"

          returnvariable="FindResourceDetailForDayResponse">

          <cfinvokeargument name="c" value="Deerwood">

          <cfinvokeargument name="d" value="">

       

      </cfinvoke>

      <cfoutput>Test value returns #FindResourceDetailForDayResponse#</cfoutput>

       

       

      However that code returns this: Test value returns org.tempuri.FindResourceDetailForDayResponseFindResourceDetailForDayResult@13d9efc

       

      The information that SoapUI returns in XML format is this:

       

      <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">

                     <calendar xmlns="">

                        <Dwc-Room-02 diffgr:id="Dwc-Room-021" msdata:rowOrder="0" diffgr:hasChanges="inserted">

                           <StartTime>10/6/2010 11:00:00 AM</StartTime>

                           <EndTime>10/6/2010 12:00:00 PM</EndTime>

                           <BusyType>Busy</BusyType>

                           <Subject>Construction Meeting</Subject>

                           <Location/>

                           <IsException>False</IsException>

                           <IsMeeting>False</IsMeeting>

                           <IsPrivate>False</IsPrivate>

                           <IsRecurring>False</IsRecurring>

                        </Dwc-Room-02>

                        <Dwc-Room-01 diffgr:id="Dwc-Room-011" msdata:rowOrder="0" diffgr:hasChanges="inserted">

                           <StartTime>10/6/2010 9:00:00 AM</StartTime>

                           <EndTime>10/6/2010 11:00:00 AM</EndTime>

                           <BusyType>Busy</BusyType>

                           <Subject>Leadership Meeting</Subject>

                           <Location/>

                           <IsException>False</IsException>

                           <IsMeeting>False</IsMeeting>

                           <IsPrivate>False</IsPrivate>

                           <IsRecurring>False</IsRecurring>

                        </Dwc-Room-01>

                        <Dwc-Room-01 diffgr:id="Dwc-Room-012" msdata:rowOrder="1" diffgr:hasChanges="inserted">

                           <StartTime>10/6/2010 12:00:00 PM</StartTime>

                           <EndTime>10/6/2010 2:00:00 PM</EndTime>

                           <BusyType>Busy</BusyType>

                           <Subject>Strategic Conversation</Subject>

                           <Location/>

                           <IsException>False</IsException>

                           <IsMeeting>False</IsMeeting>

                           <IsPrivate>False</IsPrivate>

                           <IsRecurring>False</IsRecurring>

                        </Dwc-Room-01>

                        <Dwc-Room-01 diffgr:id="Dwc-Room-013" msdata:rowOrder="2" diffgr:hasChanges="inserted">

                           <StartTime>10/6/2010 2:00:00 PM</StartTime>

                           <EndTime>10/6/2010 3:00:00 PM</EndTime>

                           <BusyType>Busy</BusyType>

                           <Subject>Board Meeting</Subject>

                           <Location/>

                           <IsException>False</IsException>

                           <IsMeeting>False</IsMeeting>

                           <IsPrivate>False</IsPrivate>

                           <IsRecurring>False</IsRecurring>

                        </Dwc-Room-01>

                     </calendar>

                  </diffgr:diffgram>

       

      How do I go about accessing the information within the parent/child nodes of the XML? This is my first time working with complex webservices in Coldfusion.

        • 1. Re: Consuming SOAP Web Services
          Big Mad Kev Level 1

          Rather then <cfoutput>Test value returns #FindResourceDetailForDayResponse#</cfoutput>

           

          Do <cfdump var="#FindResourceDetailForDayResponse#" />

           

          This may then be an CF XML Doc and you should be able to worth with it in CF

          • 2. Re: Consuming SOAP Web Services
            12Robots Level 4

            ColdFusion has several functions for working with XML Document Object Models (DOM).

             

            You can read about working with XML in CF here: http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec133ba -7fd9.html

             

            The function you will get the most use out of is XMLSearch() which will require you to learn a bit of XPath (which is pretty cool, but can be as confusing as regex).

             

            XPath search queries will allow you to dig through complex XML and retrieve nodes that you can then iterate over to accomplish what you probably need.

             

            If you have a more specific question, please reply with it.

             

            Jason

            • 3. Re: Consuming SOAP Web Services
              Dave Watts Adobe Community Professional

              This:

               

              org.tempuri.FindResourceDetailForDayResponseFindResourceDetailForDayResult@13d9efc

               

              is a Java reference to an object in memory. That object probably contains the XML, as well as methods to interact with that XML.

               

              What do you get when you use CFDUMP to view FindResourceDetailForDayResponse?

               

              To interact with the XML once you get it, CF lets you treat XML documents as if they were nested arrays and structures. So, you can iterate over them using native CF operations and functions. You can also use XML DOM API calls like you would in many other environments. Finally, you can use XPath to match nodes anywhere in your XML.

               

              Dave Watts, CTO, Fig Leaf Software

              http://www.figleaf.com/

              http://training.figleaf.com/

               

              Fig Leaf Software is a Veteran-Owned Small Business (VOSB) on

              GSA Schedule, and provides the highest caliber vendor-authorized

              instruction at our training centers, online, or onsite.

              • 4. Re: Consuming SOAP Web Services
                J_Tremain Level 1

                webshot.jpg

                That's what I get when I run cfdump

                • 5. Re: Consuming SOAP Web Services
                  J_Tremain Level 1

                  If it makes any difference here's the entire output I get when I run the WSDL thru SoupUI

                   

                  <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

                     <soap:Body>

                        <FindResourceDetailForDayResponse xmlns="http://tempuri.org/">

                           <FindResourceDetailForDayResult>

                              <xs:schema id="calendar" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">

                                 <xs:element name="calendar" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">

                                    <xs:complexType>

                                       <xs:choice minOccurs="0" maxOccurs="unbounded">

                                          <xs:element name="Dwc-Room-02">

                                             <xs:complexType>

                                                <xs:sequence>

                                                   <xs:element name="StartTime" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="EndTime" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="BusyType" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="Subject" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="Location" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="IsException" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="IsMeeting" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="IsPrivate" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="IsRecurring" type="xs:string" minOccurs="0"/>

                                                </xs:sequence>

                                             </xs:complexType>

                                          </xs:element>

                                          <xs:element name="Dwc-Room-01">

                                             <xs:complexType>

                                                <xs:sequence>

                                                   <xs:element name="StartTime" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="EndTime" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="BusyType" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="Subject" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="Location" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="IsException" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="IsMeeting" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="IsPrivate" type="xs:string" minOccurs="0"/>

                                                   <xs:element name="IsRecurring" type="xs:string" minOccurs="0"/>

                                                </xs:sequence>

                                             </xs:complexType>

                                          </xs:element>

                                       </xs:choice>

                                    </xs:complexType>

                                 </xs:element>

                              </xs:schema>

                              <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">

                                 <calendar xmlns="">

                                    <Dwc-Room-02 diffgr:id="Dwc-Room-021" msdata:rowOrder="0" diffgr:hasChanges="inserted">

                                       <StartTime>10/6/2010 11:00:00 AM</StartTime>

                                       <EndTime>10/6/2010 12:00:00 PM</EndTime>

                                       <BusyType>Busy</BusyType>

                                       <Subject>Construction Meeting</Subject>

                                       <Location/>

                                       <IsException>False</IsException>

                                       <IsMeeting>False</IsMeeting>

                                       <IsPrivate>False</IsPrivate>

                                       <IsRecurring>False</IsRecurring>

                                    </Dwc-Room-02>

                                    <Dwc-Room-01 diffgr:id="Dwc-Room-011" msdata:rowOrder="0" diffgr:hasChanges="inserted">

                                       <StartTime>10/6/2010 9:00:00 AM</StartTime>

                                       <EndTime>10/6/2010 11:00:00 AM</EndTime>

                                       <BusyType>Busy</BusyType>

                                       <Subject>Leadership Meeting</Subject>

                                       <Location/>

                                       <IsException>False</IsException>

                                       <IsMeeting>False</IsMeeting>

                                       <IsPrivate>False</IsPrivate>

                                       <IsRecurring>False</IsRecurring>

                                    </Dwc-Room-01>

                                    <Dwc-Room-01 diffgr:id="Dwc-Room-012" msdata:rowOrder="1" diffgr:hasChanges="inserted">

                                       <StartTime>10/6/2010 12:00:00 PM</StartTime>

                                       <EndTime>10/6/2010 2:00:00 PM</EndTime>

                                       <BusyType>Busy</BusyType>

                                       <Subject>Strategic Conversation</Subject>

                                       <Location/>

                                       <IsException>False</IsException>

                                       <IsMeeting>False</IsMeeting>

                                       <IsPrivate>False</IsPrivate>

                                       <IsRecurring>False</IsRecurring>

                                    </Dwc-Room-01>

                                    <Dwc-Room-01 diffgr:id="Dwc-Room-013" msdata:rowOrder="2" diffgr:hasChanges="inserted">

                                       <StartTime>10/6/2010 2:00:00 PM</StartTime>

                                       <EndTime>10/6/2010 3:00:00 PM</EndTime>

                                       <BusyType>Busy</BusyType>

                                       <Subject>Board Meeting</Subject>

                                       <Location/>

                                       <IsException>False</IsException>

                                       <IsMeeting>False</IsMeeting>

                                       <IsPrivate>False</IsPrivate>

                                       <IsRecurring>False</IsRecurring>

                                    </Dwc-Room-01>

                                 </calendar>

                              </diffgr:diffgram>

                           </FindResourceDetailForDayResult>

                        </FindResourceDetailForDayResponse>

                     </soap:Body>

                  </soap:Envelope>

                  • 6. Re: Consuming SOAP Web Services
                    Dave Watts Adobe Community Professional

                    Try dumping get_any().

                     

                    Dave Watts, CTO, Fig Leaf Software

                    http://www.figleaf.com/

                    http://training.figleaf.com/

                     

                    Fig Leaf Software is a Veteran-Owned Small Business (VOSB) on

                    GSA Schedule, and provides the highest caliber vendor-authorized

                    instruction at our training centers, online, or onsite.

                    • 7. Re: Consuming SOAP Web Services
                      J_Tremain Level 1

                      It returns back a longer list with what looks like would be functions that would be used for looping thru the XML i.e. "getAllAttributes", "getChildren", "getElementName", "getEnvelope"

                      • 8. Re: Consuming SOAP Web Services
                        Dave Watts Adobe Community Professional

                        Well, try calling some of those and see what happens!

                         

                        Dave Watts, CTO, Fig Leaf Software

                        http://www.figleaf.com/

                        http://training.figleaf.com/


                        Fig Leaf Software is a Veteran-Owned Small Business (VOSB) on

                        GSA Schedule, and provides the highest caliber vendor-authorized

                        instruction at our training centers, online, or onsite.

                        • 9. Re: Consuming SOAP Web Services
                          Jo Corless Level 1

                          What you are getting back is actually a http response and you need to

                          get at the soap body inside it

                           

                          so for my returnVariable which I've called httpResponse - I do the following

                           

                                  <cfif find( "200", #httpResponse.statusCode# )>

                                          <!--- Parse the XML SOAP response. --->
                                          <cfset soapResponse = xmlParse( #httpResponse.fileContent# ) />
                                         
                                          <!-- write a copy of the response to the file system -->
                                          <cffile action="write" 
                                          file="#session.server_root#/xmlOrders/#now()_response.xml"
                                          output="#soapResponse#" >
                              
                                          <!---
                                              Query for the response nodes using XPath. Because the
                                              SOAP XML document has name spaces, querying the document
                                              becomes a little funky. Rather than accessing the node
                                              name directly, we have to use its local-name().
                                          --->
                                          <cfset responseNodes = xmlSearch(
                                              #soapResponse#,
                                              "//*[ local-name()='SOL_Acknowledgement']"
                                              ) />

                           

                               </cfif>

                           

                          Hope that helps

                          • 10. Re: Consuming SOAP Web Services
                            J_Tremain Level 1

                            Here's my latest attempt. It seems to blow up around the CF struct-style XML node access attempt at the very bottom. The error I get is "

                            Element NAME.XMLTEXT is undefined in a Java object of type class coldfusion.xml.XmlNodeMap referenced as ''

                             

                             

                            <cfsavecontent variable="soapBody">

                             

                            <cfoutput>

                             

                             

                             

                            <?xml version="1.0" encoding="utf-8"?>

                             

                            <soap:Envelope

                             

                                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                             

                                        xmlns:xsd="http://www.w3.org/2001/XMLSchema"

                             

                                        xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

                             

                             

                             

                            <soap:Body>

                             

                             

                             

                            <FindResourceDetailForDay xmlns="http://tempuri.org/">

                             

                             

                             

                            <c>Deerwood</c>

                                  <d></d>

                                </FindResourceDetailForDay>

                              </soap:Body>

                            </soap:Envelope>

                             

                             

                             

                            </cfoutput>

                             

                            </cfsavecontent>

                             

                             

                             

                            <cfhttp

                             

                            url="http://webservice/WSExchangeMeetingRooms/exchange.asmx"

                             

                            method="post"

                             

                            result="httpResponse">

                             

                             

                             

                            <cfhttpparam

                             

                            type="header"

                             

                            name="SOAPAction"

                             

                            value="http://tempuri.org/FindResourceDetailForDay"

                             

                            />

                             

                             

                            <cfhttpparam

                             

                            type="header"

                             

                            name="accept-encoding"

                             

                            value="no-compression"

                             

                            />

                             

                             

                            <cfhttpparam

                             

                            type="xml"

                             

                            value="#trim( soapBody )#"

                             

                            />

                             

                             

                             

                            </cfhttp>

                             

                             

                            <cfif find( "200", httpResponse.statusCode )>

                             

                             

                             

                            <!--- Parse the XML SOAP response. --->

                             

                            <cfset soapResponse = xmlParse( httpResponse.fileContent ) />

                             

                             

                            <cfset responseNodes = xmlSearch(

                             

                            soapResponse,

                             

                            "//*[ local-name() = 'FindResourceDetailForDayResponse' ]"

                             

                            ) />

                             

                            <cfoutput>

                             

                             

                             

                            Code: #responseNodes[ 1 ].Code.xmlText#

                             

                            <br />

                             

                            Success: #responseNodes[ 1 ].Message.xmlText#

                             

                             

                             

                            </cfoutput>

                             

                             

                             

                            </cfif>

                            • 11. Re: Consuming SOAP Web Services
                              Miguel-F Level 3

                              I would highly recommend using cfdump while you are debugging this issue. It will keep you away from getting sidetracked from the real issue. So instead of cfoutput'ing your variables just cfdump the entire structure. That way you can get a better picture of what is happening (or not).

                               

                              Instead of this:

                               

                              <cfoutput>

                              Code: #responseNodes[ 1 ].Code.xmlText#

                              <br />

                              Success: #responseNodes[ 1 ].Message.xmlText#

                              </cfoutput>

                               

                              Do this:

                              <cfdump var="#responseNodes#">

                              • 12. Re: Consuming SOAP Web Services
                                BKBK Adobe Community Professional & MVP

                                SOAP means you have to send a SOAP XML to the web service. Do something like:

                                 

                                <!--- WSDL --->
                                <cfset wsdl_url="http://dwc-dreiman-w7e/WSExchangeMeetingRooms/exchange.asmx?WSDL">
                                        
                                <cftry>


                                    <!--- Compose SOAP message to send to Web Service--->
                                    <cfsavecontent variable="soap"><?xml version="1.0" encoding="UTF-8" ?>
                                         <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>
                                                 <ns:requestParameterName soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns="http://your_own_namespace_url">
                                                        <c xsi:type="xsd:string">bkbk</c>
                                                      <d xsi:type="xsd:string">test message from bkbk</d> 
                                                  </ns:requestParameterName>
                                              </soapenv:Body>
                                          </soapenv:Envelope>
                                    </cfsavecontent>


                                        <!--- Invoke web service to send message--->
                                        <cfhttp url="#wsdl_url#" method="post" >
                                            <cfhttpparam type="header" name="content-type" value="text/xml">
                                            <cfhttpparam type="header" name="SOAPAction" value="">
                                            <cfhttpparam type="header" name="content-length" value="#len(soap)#">
                                            <cfhttpparam type="header" name="charset" value="utf-8">
                                            <cfhttpparam type="xml" name="message" value="#trim(soap)#">
                                        </cfhttp>
                                        <p><cfoutput>#xmlFormat(cfhttp.fileContent)#</cfoutput> </p>
                                       
                                    <cfcatch type="any">
                                        <cfdump var="#cfcatch#">
                                    </cfcatch>
                                </cftry>

                                • 13. Re: Consuming SOAP Web Services
                                  J_Tremain Level 1

                                  Thanks BKBK, that worked for me. Now I'm getting the XML returned from the webservice. Now I just need to be able to query the XML data but I think I can find/figure that out on my own. Thanks everyone for the help.

                                  • 14. Re: Consuming SOAP Web Services
                                    Miguel-F Level 3

                                    I was having this same issue and found a way to get at the values while still using the cfinvoke method instead of using cfhttp.  To re-iterate when I made a cfinvoke call to the web service and dumped the result I would see an object dump with methods but no values (not the soap response I was expecting).  You are able to retrieve the values from the service call by utilizing those methods that you see returned in the object.  So for example, in this post a cfinvoke call was made to the web service and the result was stored in return variable "FindResourceDetailForDayResponse".  The cfdump that was included shows the methods returned for that web service.  In order to get the actual data from the call you can reference them like this for simple values:  FindResourceDetailForDayResponse.getSimpleValue().  For complex values (like in the example from this post) you must dig a little deeper.  If you keep cfdump'ing the returned methods you will finally get to the simple values.  Then it is just a matter of calling each method in turn, like:  FindResourceDetailForDayResponse.get_any().getStartTime() and FindResourceDetailForDayResponse.get_any().getEndTime() etc.

                                     

                                    I know this is an old post but I just wanted to get this info out here because I haven't seen it mentioned anywhere else.  You can certainly call the webservice using cfhttp as others have mentioned but then you need to deal with the resulting XML object.  By calling the methods as I have shown you can access the values directly without the need to traverse the XML tree.  If there is an issue with processing the soap response in this way then please let me know.  It seems to be working for me.

                                    • 15. Re: Consuming SOAP Web Services
                                      insuractive Level 3

                                      Miguel - one thing I would watch out for is if one of the properties associated with a getter methods does not contain a value, you will get a NULL value back.  In ColdFusion setting a variable to a NULL value will remove that variable from the memory space and give you a variable is not defined error when you try to use it.  Typically this is not a huge issue, but .NET based web services are the worst at this sort of thing (returning NULL values, that is).  I always caution users who are consuming web services using the <cfinvoke> method to check all of their getMethod() calls for NULL values or use an isdefined() check before using the variable.  Rolling that checking logic into a UDF makes it a little easier to implement.

                                       

                                      One advantage that the SOAP method has is that since you are dealing with native XML, it is a little easier to handle missing elements/attributes from your web service call.