3 Replies Latest reply on May 12, 2011 8:32 AM by WillNL

    Webservice-Problem / returnValues >= 1 / ObjectProxy vs. ArrayCollection

    cyberjunk1234

      Hey folks,

       

      after doing some research the following problem seems to be a well known one, but unfortunately I couldn't come up with a suitable solution yet, so I'm asking for help.

       

      Background:

      My Flex-Application consumes a SOAP webservice which was integrated by Flash-Builder.

      Flash-Builder created a webservice-wrapper-class with all available methods and it created proxy-classes for some of the values that returned by the webservice-methods. For example one of our operations as it shows up the the webservice-wrapper-class .as file:

       

      operation = new mx.rpc.soap.mxml.Operation(null, "methodA()");
      operation.resultElementType = valueObjects.StrongTypedClassA;
      operations["methodA"] = operation;

       

      As you can see in those 3 lines:

      1) Our method may return more than 1 value [1..N] -> List/ArrayCollection/Array/..

      2) Objects in this list are of type "StrongTypedClassA"

       

      Flex of course also auto-genereated this StrongTypedClassA (valueObjects.strongTypedClassA) with all its properties.

       

      Similar Problems:

      http://forums.adobe.com/message/92735#92735

      http://forums.adobe.com/message/2931491

       

      The problem:

      If we call this "methodA" and if the returnvalue contains more than 1 result, everything is working fine. We get an ArrayCollection which is populated with objects of class "StrongTypedClassA" in that case

       

      However, if the returnvalue contains exactly 1 result, flex creates an Object of class "ObjectProxy", not an ArrayCollection with 1 items in it (as I would like to see in next version )

       

      If you google this problem, you'll come up with a couple of possible solutions, that claim to solve this problem, for example:

      http://theruntime.com/blogs/be-sharp/archive/2008/02/26/Web-Services-and-ArrayCollections- in-Adobe-FLEX-2-How-to-Successfully-Read-Any-Number-of-XML-Nodes.aspx
      http://stackoverflow.com/questions/517238/flex-3-webservice-results-issue

       

      They both try to solve this problem, by catching this "single-return-value-case" using type-analyse of e.result in result-callback-handler and then add this single item to an self-created ArrayCollection. This does basically work, but not if you expect the items of the ArrayCollection to be of type "StrongTypedClassA" (what you generally do, if you get the chance to work with strong-typed objects).

       

      To make this a little bit more clear, here are 2 different instances of ArrayCollection, one with single-result added manually as described in those workarounds, and one that was created by the webservice-wrapping.

       

      ArrayCollection A (was manually created and filled with single return value --> e.result is ObjectProxy)

      [0] = object of type ObjectProxy

       

      ArrayCollection B (already is an ArrayCollection in webservice resultcallback handler -> e.result is ArrayCollection)

      [0] = object of type StrongTypedClassA

      [1] = object of type StrongTypedClassA

      [...] = object of type StrongTypedClassA

       

      Looking for a solution to this myself, I came back to the operation-definitions in the webservice-wrapper-class (top of the posting).

      There you can define two interesting things:

       

      1) operation.resultType

      2) operation.resultElementType

       

      First this seems to be a perfect place to find my solution, but if you have a look at integrated documentation popuping up in your flex-builder, you'll find a statement like: "If you set resultElementType, you don't have to set resultType"

      Damn it! What if I like to set it?

       

      Actually the statement is right, there's no use in setting both of these types, the resultType seems to simply get ignored as soon as you set resultElementType.

       

      I can even switch the behaviour of my problem vice-versa by defining the resultType instead of resultElementType. Then I'll get a strong-typed return in case of exactly 1 result and an "untyped" ObjectProxy in case of multiple results...

       

      Now, I'm finally at the point giving up and going the simple, but ugly way:

      Converting the returnvalue in case of ObjectProxy (=1 result) manually into the according strong-typed one by adding a new constructor to the autogenerated strongTypedClassA taking objectproxy as parameter.

       

      I don't like that, because it does one step twice, but it seems I can not find any other suitable solution. I tried casting it in many different ways, but those casts simply return null because it seems that it can not be done implicitly. Here's another source, that is helpful:

       

      http://www.docsultant.com/site2/articles/flex_internals.html#objectproxy

       

      at least this source shows you a way to acces the "plain" object-properties, it's something like:

      if (e.result is ObjectProxy) var obj = e.result.object_proxy::object;

       

      But that class still cannot be casted to the autogenerated strongTypedClassA one from webservice-wrapper.

      Anyway, if you have any good ideas on this, please let me know.

       

      And for the end:

      I really think Adobe could have done this better. There are 2 simple ways, to solve these issues by changing their implementation:

      1) If the operation-definition sets resultElementType, always make e.result an ArrayCollection, that contains zero, one or N items (3 different return values atm)

      2) Allow the user to set both properties (resultType, resultElementType) of operation definition and use them in according cases.

       

      With kind regards