9 Replies Latest reply on Jul 1, 2009 12:26 PM by churlbu

    Calling a web service that can return a collection with 1 or more objects

    JoshBeall Level 1
      Hi All,

      I have a web service that can return a "Contacts" collection that looks like this in XML:

      <Contacts>
      <CurrentInformationContact>
      <ContactType>string</ContactType>
      <ContactValue>string</ContactValue>
      </CurrentInformationContact>
      <CurrentInformationContact>
      <ContactType>string</ContactType>
      <ContactValue>string</ContactValue>
      </CurrentInformationContact>
      </Contacts>

      Example ContactTypes are "Home" and "Work". The ContactValues would then be phone numbers.

      It is possible to have only one CurrentInformationContact element, or you could have 2 or more. If you have only one, the web service result must be accessed like this:

      trace(result.Contacts.ContactType + " phone is " + result.Contacts.ContactValue);

      However, if there are 2 or more CurrentInformationContact elements returned, you need to access the Contacts collection like this:

      trace(result.Contacts[0].ContactType + " phone is " + result.Contacts[0].ContactValue);

      These two methods of accessing the contacts collection are mutually exclusive. Meaning that if there is exactly one Contact, you cannot use array indices (it isn't an array); if there are 2 or more, you have to specify the array indices.

      This is a problem, because it means that for any collection that could contain 1 or more items, I have to check to see if it's a collection (ArrayCollection, in AS), and if so, treat it as a collection (using numeric indices). If it is not a collection, I access the objects directly.

      Requested enhancement: can we get web service results that can be accessed using numeric array indices even in instances where there is only one object in the collection. This would keep backwards compatibility with any existing code, and it would allow us to access any collection returned by a web service in the same way, regardless of whether or not it has 1, 2, or 100 items in the collection.

      The implementation details could prove a little challenging, but I see real value in this feature.

      Of course, all this is solved very nicely if we get proxy class generation based on a WSDL. Because proxy class generation will be new, we can go with the more intuitive approach of strongly typing something as either a regular object with properties, or an ArrayCollection. Anytime an element could contain more than one direct child element (e.g., my contacts example above), it should be strongly typed as a collection, even if there is only one element in the collection.
        • 2. Re: Calling a web service that can return a collection with 1 or more objects
          JoshBeall Level 1
          I'm calling a SOAP web service, not a POX ("plain old XML") web service. HTTPService is for POX web services.

          There doesn't appear to be a "resultFormat" property on the WebService class:
          http://livedocs.adobe.com/flex/201/langref/index.html

          Even if there was, I'm not entirely sure this would be what I'm looking for. I don't want everything to be an array or collection, I only want elements that the WSDL defines as having the possibility of repeating (as opposed to having one and only one instance that can occur) to *always* be arrays. In other words, the WSDL is telling us that this element should be an array, even if the array only has one element. Flex should observe this instruction.

          And as I think about this again, I think the best answer is not change the current behavior in any fashion, but to add a toolkit for strongly typed proxy class generation based on a WSDL document. Then you'd get code completion, too!
          • 3. Calling a web service that can return a collection with 1 or more objects
            GabiD.
            Hi Josh,

            Flex Builder 3 includes a tool that will provide the functionality you're looking for. This is the "Import Web Service (WSDL)" wizard that takes a wsdl location and can generate a proxy class that will allow you to directly call the web service operations directly and get strongly typed results. Regarding your example, the return type will always be an array even if it only has one element.

            The latest engineering drop includes this tool (not available in the current beta build), and you can access the wizard from File>Import>Flex>Import Web Service (WSDL) or from the Data>Import Web Service (WSDL)... menu option.
            Hints on how to use the proxy class are provided as comments at the top of the main generated class. Using this approach also enables code hinting on the operations exposed by the web service and the corresponding parameters you have to pass to each operation.

            Give the tool a try and post back if you need assistance using it or if you encounter any problems.
            • 4. Re: Calling a web service that can return a collection with 1 or more objects
              RioVic
              I agree, this issue is a real pain.. Checking for the null values and the singletons every time you access a web service is bad. Having to use a sophisticated tool that is in Beta with Flex 3 is also bad. Does anyone have a simple solution? I am at the point where I am going to chagne all my web services to return a minimum of two records just to fool the Flex parser!!! By the way, it is NOT solved by changing the resultFormat to "array".
              • 5. Re: Calling a web service that can return a collection with 1 or more objects
                RioVic Level 1
                What is even more annoying is that in the book, "Adobe Flex 2 Training from the Source" Jeff Tapper and Matthew Boles use this kind of implicit conversion all over the place, never saying a word about the run time errors that will occur when the lists and combo boxes they are populating have only one value. One would expect more from the experts.
                • 6. Re: Calling a web service that can return a collection with 1 or more objects
                  JoshBeall Level 1
                  quote:

                  Originally posted by: RioVic
                  Having to use a sophisticated tool that is in Beta with Flex 3 is also bad.
                  It might not be as bad as you think. Let's wait and give it a try.

                  Granted, I'm already biased towards the proxy class technique, because I use Visual Studio, and that's the standard procedure for calling web services.

                  But it works great, you get strongly typed results and code-completion ("intellisense", in MS-speak), and you don't have to check for an array/not array.



                  quote:

                  Originally posted by: RioVic
                  Does anyone have a simple solution? I am at the point where I am going to chagne all my web services to return a minimum of two records just to fool the Flex parser!!! By the way, it is NOT solved by changing the resultFormat to "array".
                  I suppose the only other solution would be to load up the XML you got back, and parse the XML yourself? DOM access of the XML document wouldn't have this problem.

                  I'd really encourage you to give the proxy class from WSDL generator a try before you judge it (I haven't used it myself, so I can't judge it either). If they've implemented it as well as Visual Studio has, it's quick and painless, and gives you a much nicer way to interact with your web services. And as a bonus, you save a roundtrip on the WSDL loading (it's done at class generation time, rather than runtime).

                  Incidentally, I have a speculation on why the webservice exhibits the behavior we're seeing -- I suspect it doesn't actually inspect the WSDL for the types it's going to get back. It just parses it using the standard XML to object techniques it normally uses. So at parse time, it knows nothing about whether or not a particular XML node should be an array (has the possibility of having multiple children) or not (has at most one child).

                  Best would be to get a resolution both to the issues with the WebService return results, *and* to get an excellent proxy class generator. However, if we can only have one, I'd prefer to have the WebService ignoring the types defined in the WSDL (and thus exhibiting the current behavior), but have an excellent proxy class generator that gives me strongly typed results *and* avoids the WSDL load roundtrip.

                  If it comes down to finishing the polish on the proxy class generator, or fixing this issue before Flex 3.0 is released, I'd request we do the former, and leave the latter to Flex 3.1 (or however Adobe handles minor release -- Flex 3 update 1?)

                  -Josh
                  • 7. Re: Calling a web service that can return a collection with 1 or more objects
                    RioVic Level 1
                    OK, thanks you for the quick reply. I doubt if the proxy class solution will work at all in my case, since my web services are "polymorphic", i.e. they return different types of arguments based on the opcodes sent to them. But you are right I was getting a little overheated about this issue. Here is the workaround, assuming your web service always sends at least one record even if it is just an error or a message that the result set is empty. Put this in each result handler:

                    if (event.result.records.record is ObjectProxy) {
                    dataArray.addItemAt(event.result.records.record,0)
                    }
                    else {
                    dataArray = event.result.records.record;
                    }

                    If you want to get a little more advanced, put something that checks for errors and messages from the web service in the first section, since these kinds of results will always be singletons.
                    • 8. Re: Calling a web service that can return a collection with 1 or more objects
                      JoshBeall Level 1
                      Very interesting. What are you using for your backend web services? Java? ASP,NET? PHP? Just curious.

                      I'd also be curious to see how the proxy class generator handles a web service that returns a generic type, like "System.Object" in .NET.

                      -Josh
                      • 9. Re: Calling a web service that can return a collection with 1 or more objects
                        churlbu

                        I am using the proxy class generator in Flex Builder 3 and the code that's generated assumes the result is an Array.  The problem is when a single value is returned from the web service (Axis 2), it doesn't come in as an array, it's just a single typed object.  Is this a bug on one side or the other?  Am I doing something wrong?

                         

                        Thanks,

                        Chuck