31 Replies Latest reply on Feb 27, 2008 1:42 PM by wltiii

    Complex data type help sought

    wltiii
      Hi All,

      This seems like it should be simpler than it has been for me, but I am neither an expert with webservices nor CF. Though not a newbie, my guess is that there is something fundamental I am missing. I have sought answers to this and read many articles, but either the suggestions do not work, do not apply or talk of writing a wrapper in java. Perhaps it isn't even possible to represent this in CF, but I have not seen anything that says that, either.

      Anyway, the webservice I call returns an array of objects named TABLE_OF_BAPIRET2 (if I am understanding properly. After making the call, doing a cfdump of the result I get Variable TABLE_OF_BAPIRET2 is undefined. See attached code below.

      This is not surprising after reading Handling complex data types. So, I changed the cfdump to reference TABLE_OF_BAPIRET2.MESSAGE. This did not work (I did not expect it to since there is nothing in the statement referencing the array element). However, it did give me more promising results: Element MESSAGE is undefined in TABLE_OF_BAPIRET2. This tells me I can reference the return variable as suggested by the cited article, but I must be doing something wrong. NOTE: when I specified an index by stating TABLE_OF_BAPIRET2[1].MESSAGE, I go back to the error Variable TABLE_OF_BAPIRET2 is undefined. This I did not expect and am now stumped.

      I've attached below the relevant section of the wsdl defining the structure. I am also attaching the SOAP message that is returned.

      Is it even possible to decipher this object? Or, do I need to use java (I am comfortable with that, but would rather use CF). I strongly believe this is not the case, that there is something fairly simple I am overlooking, but cannot see it. So, any help is greatly appreciated!

      TIA,

      bill
        • 1. Re: Complex data type help sought
          wltiii Level 1
          I did, BTW, try to use returnVariable="TABLE_OF_BAPIRET2[]" as is suggest by the article Did you know: Array of components. That, too, errored, but for a different reason. The error states The string "TABLE_OF_BAPIRET2[]" is not a valid ColdFusion variable name.

          Any pointers or suggestions?

          bill
          • 2. Re: Complex data type help sought
            Level 7
            wltiii wrote:
            > I did, BTW, try to use returnVariable="TABLE_OF_BAPIRET2[]" as is
            > suggest by the article
            > http://www.coldfusionjedi.com/index.cfm?mode=entry&entry=FAE8F3B9-BC72-0C47-D669
            > E522B0559213. That, too, errored, but for a different reason. The error states
            > The string "TABLE_OF_BAPIRET2[]" is not a valid ColdFusion variable name.
            >
            > Any pointers or suggestions?
            >
            > bill
            >

            That post is meant to talk about the Web Service creation side not the
            consumption side. On the consumption side, '[]' are illegal characters
            in a variable name.

            You original code should have produced something if something is being
            returned by the web service.

            If you put the webservice URL in a browser do you get the correct WSDL file?

            Where did you capture the SOAP response?

            Are you sure something is being sent and received. Can you use tools to
            spy on the actual requests and responses?

            • 3. Re: Complex data type help sought
              wltiii Level 1
              quote:

              That post is meant to talk about the Web Service creation side not the consumption side.


              Really? I didn't see anything in the article that suggested that, and since it specifically was speaking of returnType, I thought it might work. However, the article does seem to be only about returns from components. I am assuming you are referring to the Did You Know: Arrays of Components article posted at coldfusionjedi.

              quote:

              You original code should have produced something if something is being returned by the web service


              I would've thought so, but that does not seem to be the case, and the article "Handling Complex Data Types", in the section talking specifically about consuming a service, suggests otherwise:

              quote:

              You access elements of the variable myReturnVar using dot notation in the same way that you access structure fields. If a complex type has nested elements, in the way a structure can have multiple levels of nested fields, you use dot notation to access the nested elements, as in a.b.c.d, to whatever nesting level is necessary.

              However, the variable myReturnVar is not a ColdFusion structure . It is a container for the complex type, but has none of the attributes of a ColdFusion structure. Calling the ColdFusion function isStruct on the variable returns False.


              (Emphasis mine).

              quote:

              If you put the webservice URL in a browser do you get the correct WSDL file?


              Yes.

              quote:

              Where did you capture the SOAP response?


              The host developer has a tool. Sorry, I don't know the name. He was able to capture both the SOAP request and response. He did so when he ran a java version, and again when I ran my CF version. The SOAP response looks exactly as expected (the same when called by both java and CF).

              quote:

              Are you sure something is being sent and received. Can you use tools to spy on the actual requests and responses?

              By capturing the SOAP response, I am sure the request must have been received by the service. Since there are no errors unless I try to reference the returnVar, it appears that the response must have been received. I answered about the tools above. Considering that under the condition that I am using dot notation and getting the error that the element MESSAGE is undefined strongly indicates that I do have an object of some sort, just not properly parsing it.
              • 4. Re: Complex data type help sought
                Level 7
                Ok lets be clear here. Are you getting NO response or that the response
                is not the complex variable you are expecting.

                Looking at the soap response you maybe just getting a XML packet that CF
                is treating as a string at this point. Until this XML is processed into
                an XML structure you would not be able to use dot notation to access
                interior elements.

                So does the <cfdump var="#Table_of_Bapiret2#"> show something on the
                screen or does it throw an 'undefined' error?

                • 5. Re: Complex data type help sought
                  wltiii Level 1
                  quote:

                  So does the <cfdump var="#Table_of_Bapiret2#"> show something on the screen or does it throw an 'undefined' error?

                  The statement <cfdump var="#TABLE_OF_BAPIRET2#" /> throws the error Variable TABLE_OF_BAPIRET2 is undefined.

                  quote:

                  Looking at the soap response you maybe just getting a XML packet that CF is treating as a string at this point. Until this XML is processed into an XML structure you would not be able to use dot notation to access interior elements

                  This sounds like a promising avenue. However, I just ran the again with the attached code and the isDefined returns NO. I am confused.
                  • 6. Re: Complex data type help sought
                    Level 7
                    What happens with this code.

                    <cfset ws =
                    createObject("webservice"," http://sapcrd.comfort.com:8000/sap/bc/srt/rfc/sap/Z_YXG_SIMPLE_IN
                    PUT_TEST_WS?sap-client=300&wsdl=1.1")>

                    <cfdump var="#ws#">

                    P.S. My day is done in about 45 minutes. I'll see any responses after
                    that time tomorrow.
                    • 7. Re: Complex data type help sought
                      -==cfSearching==- Level 4
                      quote:


                      wltiii wrote:
                      Considering that under the condition that I am using dot notation and getting the error that the element MESSAGE is undefined strongly indicates that I do have an object of some sort, just not properly parsing it.



                      To interject for a moment: Not neccessarily. CF would return that same error if the object does not exist. For example, you would get the same message from this single line of code

                      <cfoutput>#NonExistantStruct.Message#</cfoutput>

                      Element MESSAGE is undefined in NONEXISTANTSTRUCT.

                      So in this case I would believe what IsDefined is reporting ie. the object does not exist.
                      • 8. Re: Complex data type help sought
                        wltiii Level 1
                        Point taken. However, I still believe something must be coming back for a few reasons.

                        First and foremost is that we did capture the SOAP response, so unless something happened between the transmission and the reception of the response that has gone undetected, or unless CF rejected the response without throwing any type of error, then I believe I must be getting a response.

                        Second, the documentation cited earlier, Handling complex data types , states that it is not a CF structure, rather it is a container. It also states that isStruct will return false. I inferred from the quoted section of documentation that CF does not really recognize the returned object, except through explicit reference to the elements contained therein.

                        Third, I had at one pointed created a var <cfset TABLE_OF_BAPIRET2 = "" /> prior to the invoke, dumped it, then invoked, then dumped again, whereupon the var did not exist. So, something happened to destroy the var. What, I don't know.

                        Obviously, some of what I state above will expose gaps in my CF knowledge. Be gentle :-)

                        bill
                        • 9. Re: Complex data type help sought
                          wltiii Level 1
                          I would try that, but I cannot figure out how to specify the user and pw in the call as I can with CFINVOKE.

                          I work with this client only Mon/Tue/Wed, so your leaving in 45 minutes really is not issue. In fact, your effort at helping me solve this is truly appreciated. It wouldn't be very politic of me to rise to anger for your working a normal day rather than spending all your time helping me! Actually, I would have probably been back to this sooner, but am also in crunch mode with my other client, plus I bought a house that I am having remodeled and at the same time trying to move into, as well as working on some of the stuff to complete the remodeling more quickly (painting, flooring, etc.), so I've had no extra time available for this project, just what I must put into it.
                          • 10. Re: Complex data type help sought
                            wltiii Level 1
                            Oh, and one more thing makes me believe that something is being returned. The host developer had created a very simple service that took a string and returned a string. I had no problem with that. Unfortunately, because of complexities in his environment, in order to become somewhat more complex, he had to become quite a bit complex. No middle ground, sadly. But, because the simple service worked, and because this service works from a java call, I have no reason to believe that nothing is being returned.
                            • 11. Re: Complex data type help sought
                              -==cfSearching==- Level 4
                              wltiii,

                              I do not know for certain whether anything is being returned or not. Just that according to ColdFusion if it is receiving a response, it is somehow not being properly being converted into an object you can use. As evidenced by the fact that your return variable is undefined. Though "no response" would seem to be a more likely cause.

                              You can add or retrieve soap headers using some of the built in soap functions.

                              AddSOAPResponseHeader
                              GetSOAPResponse
                              GetSOAPResponseHeader

                              So what happens if you try Ian Skinner's code above? You can use AddSOAPResponseHeader to add the username and password and also GetSOAPResponse/Header to view the response?
                              • 12. Re: Complex data type help sought
                                wltiii Level 1
                                I've attached the code I ran below (url, user/pw hidden). The first two dumps show the request and response, and they appear as I expect. The third, however, the one containing the result, still gives me an undefined error. I've also attached the SOAP response. NOTE: the integer 2 in the request determines how many rows are returned within BAPIRET2.

                                So, again, it looks like I am just not interpreting this response properly. You would think it would be simple enough to parse an array of structures. :-(



                                • 13. Re: Complex data type help sought
                                  Level 7
                                  wltiii wrote:
                                  > -------------------------------------------------
                                  > my soap response
                                  > -------------------------------------------------
                                  > <soap-env:Envelope xmlns:soap-env=" http://schemas.xmlsoap.org/soap/envelope/">
                                  > <soap-env:Body>
                                  > <n0:Z_YXG_SIMPLE_INPUT_TESTResponse
                                  > xmlns:n0="urn:sap-com:document:sap:rfc:functions">
                                  > <BAPIRET2>
                                  > <item>
                                  > <TYPE>S</TYPE>
                                  > <ID>Trillium</ID>
                                  > <NUMBER>001</NUMBER>
                                  > <MESSAGE>This is a test.</MESSAGE>
                                  > <LOG_NO/>
                                  > <LOG_MSG_NO>000000</LOG_MSG_NO>
                                  > <MESSAGE_V1/>
                                  > <MESSAGE_V2/>
                                  > <MESSAGE_V3/>
                                  > <MESSAGE_V4/>
                                  > <PARAMETER/>
                                  > <ROW>0</ROW>
                                  > <FIELD/>
                                  > <SYSTEM/>
                                  > </item>
                                  > <item>
                                  > <TYPE>S</TYPE>
                                  > <ID>Trillium</ID>
                                  > <NUMBER>002</NUMBER>
                                  > <MESSAGE>This is a test.</MESSAGE>
                                  > <LOG_NO/>
                                  > <LOG_MSG_NO>000000</LOG_MSG_NO>
                                  > <MESSAGE_V1/>
                                  > <MESSAGE_V2/>
                                  > <MESSAGE_V3/>
                                  > <MESSAGE_V4/>
                                  > <PARAMETER/>
                                  > <ROW>0</ROW>
                                  > <FIELD/>
                                  > <SYSTEM/>
                                  > </item>
                                  > </BAPIRET2>
                                  > </n0:Z_YXG_SIMPLE_INPUT_TESTResponse>
                                  > </soap-env:Body>
                                  > </soap-env:Envelope>
                                  >

                                  Which dump produced this output? 'Req', 'Resp' or 'OUT'?
                                  • 14. Re: Complex data type help sought
                                    wltiii Level 1
                                    This is the SOAP RESPONSE. What you are actually seeing is a result of a couple other statements that I added that I copied and pasted, but this shows all the same values as in the CFDUMP of the response. Specifically the lines added were:
                                    1) XMLText = ToString(resp);
                                    2) <cfscript>this.DebugLog.logEvent(#XMLText#);</cfscript>

                                    The updated code is shown attached. It is the call to the logger that produced this output (line 2 above).
                                    • 15. Re: Complex data type help sought
                                      Level 7
                                      As you have noted, you are definitely sending and receiving requests and
                                      responses. I do not know why you are having difficulty after this
                                      point. I do know I have used web services where I needed to send and
                                      receive complex data types and it does work.

                                      Can you precess the 'resp' variable to get what you want? Is it a
                                      string or an XML structure?

                                      • 16. Re: Complex data type help sought
                                        wltiii Level 1
                                        It is an xml struct, apparently, at least the function IsXml returns YES. I have been trying for hours, with no luck, at parsing the response, however. The SOAP response, of course, is the same as shown before. So, perhaps, you can spot something in my code that prevents my being able to successfully use the XmlSearch function, or to properly display results, or whatever it is I am doing wrong. I've attached my latest code (a snippet of what has been previously shown), and the results. The TYPE should have two occurrences, as far as I can see. So, the having the results from the CFDUMP state array [empty] is confusing. Being empty, that explains why the reference to type[1] returns The element at position 1 cannot be found. I just don't understand why it should be empty. Something wrong with my search? Something wrong with my subsequent reference to type?
                                        • 17. Re: Complex data type help sought
                                          Level 7
                                          wltiii wrote:
                                          > ----------------------------------------------------
                                          > my code snippet
                                          > ----------------------------------------------------
                                          > OUT = ws.Z_YXG_SIMPLE_INPUT_TEST(#myArray#, 2, "This is a test.");
                                          > req = getSOAPRequest(ws);
                                          > resp = getSOAPResponse(ws);
                                          > XMLText = ToString(resp);
                                          > </cfscript>
                                          > <cfset mydoc = XmlParse(XMLText)>

                                          The above line should be redundant. I.E. turning an XML structure into
                                          a string then parsing that string into an XML structure seems
                                          unnecessary to me. You should try just using 'resp' everywhere you use
                                          'mydoc' in the following code.

                                          > <cfset type = XmlSearch(mydoc,
                                          > "/soap-env:Envelope/soap-env:Body/Z_YXG_SIMPLE_INPUT_TESTResponse/BAPIRET2/item/
                                          > TYPE")>

                                          You might try a simpler search and not worry about all the intermediate
                                          layers. Try <cfset type = XMLSearch(mydoc,'//item')>

                                          > <cfdump var="#type#">
                                          > <cfoutput>
                                          > <br>Is it well formed XML text? #IsXML(XMLText)#
                                          > <br>type=[#type[1].XmlValue#]

                                          You should also be able to just access the xml structure directly.
                                          Another line of code to play with:

                                          <cfdump
                                          var="#mydoc['soap-env:Envelope']['soap-env:Body']['n0:Z_YXG_SIMPLE_INPUT_TESTResponse'][' BAPIRET2']#">

                                          If I've mistyped a layer in there, you may start at a higher point and
                                          work your way done the node tree.

                                          You may notice the choice of bracket "array" notation over dot notation.
                                          When you have complex node names such as this SOAP response there are
                                          illegal characters that disallow the use of dot notation. Array
                                          notation allows one to access these types of XML nodes.

                                          Again my day is done at ~3:30pm US Pacific Time. I will probably see
                                          any response tomorrow. Good Luck until then.

                                          Ian

                                          • 18. Re: Complex data type help sought
                                            -==cfSearching==- Level 4
                                            wltiii,

                                            Try the tip here.

                                            ...
                                            <cfset result = XmlSearch(mydoc, "//*[local-name()='item']/")>
                                            <cfdump var="#result#">
                                            • 19. Re: Complex data type help sought
                                              wltiii Level 1
                                              Okay! Great! I accessed the TYPE element! I am sure I can now get to all the elements in the structure. Thanks so much for all of your help!

                                              For those that are reading this now or in the future, a snippet from the final bits of code are attached. I probably do not need to create the mydoc var and could just use var resp instead, but have not tried that.

                                              FWIW - I think having to parse the SOAP response is a horrible kludge. If I had just written the java code after running WSDL2java, it would have taken me far less time. However, I am stubborn and wanted to make CF do what it is supposed to do. Being that this is just a test web service, we'll have to see how well the solution works for me going forward. Ultimately, however, I would really like to know how to parse returnVariable.
                                              • 20. Re: Complex data type help sought
                                                wltiii Level 1
                                                yes, I know the conversion to mydoc was unnecessary. that is legacy code from one of the many attempts i made at trying to find a solution.

                                                i tried the bracket notation at some point and it did not work. perhaps i miskeyed something. i will give that another shot.

                                                again, i appreciate the feedback :-)

                                                bill
                                                • 21. Re: Complex data type help sought
                                                  -==cfSearching==- Level 4
                                                  wltiii,

                                                  Try Ian Skinner's suggestion too. XMLSearch(mydoc, "//item") may work as well.

                                                  I am still curious about this too. Do you have a public WSDL of this simple test by any chance?
                                                  • 22. Re: Complex data type help sought
                                                    wltiii Level 1
                                                    Yes, I thought I would try that form of search as well.

                                                    I haven't worked with CF for about 2 years prior to the end of this January, then only for 9 months or so, and not before that since 2000 (a lot changed between those two times!), and then I was leading, not doing much coding, for about a little over a year. For someone with years of experience in many other languages (much more than I would care to admit! hahahaha!), it has been very easy to get into complex tasks quickly. Sadly, it means I have not always been exposed to some of the more obvious things, or I've forgotten what I was exposed to (because of the gaps in using CF mostly). The "relative" form of search was something that I knew must exist, but I had not come across it again. Once I saw Ian's response, I knew I had seen it the last time I was writing CF.
                                                    • 23. Re: Complex data type help sought
                                                      Level 7
                                                      wltiii wrote:
                                                      > Once I saw Ian's response, I knew I had seen it the last time I was
                                                      > writing CF.
                                                      >

                                                      To be fair that is XML XPath syntax not ColdFusion syntax other then
                                                      that ColdFusion uses XPath for this purpose.

                                                      I just want to clarify that this is not the 'normal' way to consume a
                                                      web service. Your first examples is what I would have expected to work.
                                                      Why they did not is a mystery. This was a way to get around the
                                                      unknown issue and get you access to your results.

                                                      As cfSearching asked, I would be curious to see the WSDL for this
                                                      exchange. This is stretching my solid knowledge of web services and how
                                                      it all fits together, but my assumption is that for CF to auto-magically
                                                      parse the SOAP response and return the desired complex data, the WSDL
                                                      would have to tell it how to do this.

                                                      The solution we cobbled together over the last couple of days, in
                                                      effect, bypasses the WSDL. Instead you are decoding the SOAP response
                                                      manually. My wild eyed guess is that the WSDL may not properly tell CF
                                                      how to decode the SOAP response and that is why you where not getting a
                                                      result with the simpler code.
                                                      • 24. Re: Complex data type help sought
                                                        wltiii Level 1
                                                        I may have seen that syntax in contexts other than CF development, then, such as java. I have not done much with web services in any environment, but did do some support of existing web service functions in a java environment for nearly two years starting midway through 2003.

                                                        I understand that this is a work around, a kludge. I would like to know why I have been unable to process the returnvar, and because there is a little slack right now in the project, I can play with this some more. So, feel free to toss out other suggestions. Because we did find a work around, it gave me other ideas to try, which I will do so today. But, as always, this window of slack time will close quickly.

                                                        Since you are both interested in the wsdl, I am attaching the complete wsdl here. I don't know how much that will help. FWIW, the WSDL2Java tool (using the jars installed with CF) seemed to work fine (I never ended up testing the java option, however, since it seemed we were making a lot of progress staying purely in CF). Unfortunately, I cannot expose access to the service to the public.
                                                        • 25. Re: Complex data type help sought
                                                          wltiii Level 1
                                                          Okay, here are some interesting results that may provide more input. See attached code. When CF tried to execute the CFDUMP with the label result of bracket array view 5, I received the error coldfusion.runtime.UndefinedElementException: Element SOAP-ENV:Envelope is undefined in a Java object of type class coldfusion.xml.XmlNodeList referenced as . Note the incomplete statement. I have also tried this by dropping the reference to item and going directly to TYPE. That produced the same results. It is interesting, though, that the relative search for item did work (both versions, which I expected). Nothing jumps out at me as to why dump 4 works and dump 5 does not.

                                                          bill
                                                          • 26. Re: Complex data type help sought
                                                            Level 7
                                                            wltiii wrote:
                                                            > Nothing jumps out at me as to why dump 4 works and
                                                            > dump 5 does not.

                                                            What does dump 4 actually show? Can you provide a copy or picture of it
                                                            somewhere public?
                                                            • 27. Re: Complex data type help sought
                                                              wltiii Level 1
                                                              it may take a couple days to publish. i am moving from one residence to another, still packing, remodeling the new place, painting, etc., movers are showing up friday, so i have not spent any time trying to get my network up and running. due to size restrictions, i cannot attach the html code here, even though i have tried to remove extraneous bit of information and code. i don't know where i'd publish a photo. however, i've attached a snippet here that may provide enough info for you. of course, you'll have to copy and paste it somewhere to view it. if you want me to publish the whole page, let me know. FWIW - i don't know where i'd publish the photo.
                                                              • 28. Re: Complex data type help sought
                                                                Level 7
                                                                <cfdump label="result of bracket array view 4"
                                                                var="#resp['soap-env:Envelope']['soap-env:Body']['n0:Z_YXG_SIMPLE_INPUT_TESTResp
                                                                onse']['BAPIRET2']#">

                                                                <cfdump label="result of bracket array view 5"
                                                                var="#resp['SOAP-ENV:Envelope']['SOAP-ENV:Body']['n0:Z_YXG_SIMPLE_INPUT_TESTResp
                                                                onse']['BAPIRET2']['item']#">

                                                                When I looked closer at these two examples there is a very subtle
                                                                difference between the two. The case of elements. In view 4 you have
                                                                'soap-env' in view 5 you have 'SOAP-ENV'. You may be dealing with one
                                                                of the few places where case matters in ColdFusion. I know the standard
                                                                indicates that XML is case sensitive, but CF usually is not. Maybe in
                                                                this situation, it is.


                                                                • 29. Re: Complex data type help sought
                                                                  wltiii Level 1
                                                                  Good catch! That made the difference. Now all the dumps show what I expect.

                                                                  Confusingly, though, the following three searches work, and the fourth does not (as evidenced by an empty arry when dumping type[/]), yet, the dump (view 6) that follows that does work. I went back to this to make sure the capitalization was consistent. I know, I've left off the namespace indicator to Z_YXG_SIMPLE_INPUT_TESTResponse, the reason being is that by specifying it the exception message Prefix must resolve to a namespace: n0 was thrown.

                                                                  Oh, well...

                                                                  bill

                                                                  • 30. Re: Complex data type help sought
                                                                    Level 7
                                                                    wltiii wrote:
                                                                    > I've left off the namespace indicator to
                                                                    > Z_YXG_SIMPLE_INPUT_TESTResponse, the reason being is that by specifying
                                                                    > it the exception message Prefix must resolve to a namespace: n0 was
                                                                    > thrown.

                                                                    That made me wonder. I went back to the WSDL you provided and I did not
                                                                    see any name space defined for 'n0'. I wonder if that means anything?
                                                                    Could this be the source of the problem that the original code did not
                                                                    work because CF could not resolve elements in the SOAP response with a
                                                                    'n0' name space?

                                                                    I don't know enough about name spaces, XML, WSDL, SOAP and web service
                                                                    to say if this matters or not.
                                                                    • 31. Re: Complex data type help sought
                                                                      wltiii Level 1
                                                                      neither do i, unfortunately. i'll run this past some others to see if they have any idea.

                                                                      bill