Skip navigation
Currently Being Moderated

Invoke webservice with complex types

Apr 13, 2012 8:07 AM

Hi

 

I am trying to invoke a .net webservice method that receives an array of strings an i noticed that if i do this:

 

<cfscript>

     text = arraynew(1);

     text[1] = "Hello";

     text[2] = "world";

</cfscript>

 

<cfinvoke method="Hello"

  webservice="http://localhost/Service1.asmx?wsdl"

  returnvariable="response">

     <cfinvokeargument name="array" value=#text#/>

</cfinvoke>

 

I get this error

Cannot perform web service invocation Hello.

The fault returned when invoking the web service operation is:

''java.lang.IlligalArgumentException: argument type mismatch

 

however if i do this it works well:

 

<cfscript>

     root = structnew();

     text = arraynew(1);

     text[1] = "Hello";

     text[2] = "world";

     root.string=text;

</cfscript>

 

<cfinvoke method="Hello"

  webservice="http://localhost/Service1.asmx?wsdl"

  returnvariable="response">

     <cfinvokeargument name="array" value=#root#/>

</cfinvoke>

 

I know this has to do with the generated java proxy because he generated a structure called ArrayOfString with a property called string (what i am replicating in the "root" variable).... Is there any way around this, or this is the right way to do it? It is a bit painfull to do it like this...

 

Thanks.

 
Replies
  • Currently Being Moderated
    Apr 14, 2012 2:03 AM   in reply to Rockit8

    I can imagine that. Run the following code, and you will find that a ColdFusion array isn't a Java array at all, but a Java vector!

     

    <cfscript>

         text = arraynew(1);

         text[1] = "Hello";

         text[2] = "world";

    </cfscript>

     

    <cfoutput>

        text: #text.getClass().getsuperclass().getname()#

    </cfoutput>

     

    One of the methods of the java.util.Vector class is toArray(). So, have a go with

     

    <cfscript>

         text = arraynew(1);

         text[1] = "Hello";

         text[2] = "world";

         textArray = text.toArray();

    </cfscript>

     

    <cfinvoke method="Hello"

      webservice="http://localhost/Service1.asmx?wsdl"

      returnvariable="response">

         <cfinvokeargument name="array" value="#textArray#" />

    </cfinvoke>

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 16, 2012 3:37 AM   in reply to Rockit8

    Rockit8 wrote:

     

    I tried calling the toArray() but throws the same type mismatch error

    Sorry to hear that. We'll search on of course.

     

    Dumping both the text and the textArray returns the same thing.

    Not really. ColdFusion tells you they are both arrays, which is true. However, text is a ColdFusion array (a Java vector), whereas textArray is a Java Object array.

     

    <cfoutput>

        text: #text.getClass().getsuperclass().getname()#<br>

        textArray: #textArray.getClass().getname()#

    </cfoutput>

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 16, 2012 3:40 AM   in reply to Rockit8

    What is the signature of the hello method? Could you show us the WSDL?

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 16, 2012 4:31 AM   in reply to Rockit8

    Ah, a String[]! You could simulate it using the following, even more compact, code:

     

    <cfscript>

         text = toString("Hello,World").split(",");

    </cfscript>

     

    <cfinvoke method="Hello"

      webservice="http://localhost/Service1.asmx?wsdl"

      returnvariable="response">

         <cfinvokeargument name="array" value="#text#" />

    </cfinvoke>

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 16, 2012 5:29 AM   in reply to Rockit8

    Rockit8 wrote:

     

    True, but that would only work in case of String[]!

    Does it work?

     

    I can fix the problem and develop something generic that does that kind of plumbing code for me...which would take me like 10 minutes or less to do.

     

    I just posted this to know if there were any alternatives to my aproach...maybe a specific wsdl2java parameter that i dont know about.

    I do believe that you, as client, should not aim to be generic. In the client-server model, the server (in this case, the web service) has the obligation to tell you precisely what type of argument it expects. If the server requires a string array, then you have to pass it a string array. 

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 16, 2012 5:38 AM   in reply to Rockit8

    Rockit8 wrote:

     

    Exactly...the server IS expecting a string[] as you can see by the signature of the method.

     

    If i call it in a .Net client i invoke the method with a string[] as parameter, from the coldfusion side i cannot do that because of the generated proxy...the problem is in the proxy generation.~

     

    I'm guessing there is nothing i can do about that...

    Very clear.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 16, 2012 5:57 AM   in reply to Rockit8

    Rockit8 wrote:

     

    No, it does not...the java proxy is expecting the structure i specified above.

    Out of curiosity, what error message did you get when you passed the string array?

     

    Added update: I thought it might be a good idea to add the attribute refreshWSDL = "yes" to cfinvoke, during your tests, to prevent ColdFusion from reusing the cached version of the proxy.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 16, 2012 6:03 AM   in reply to Rockit8

    Rockit8 wrote:

     

    Passing the ColdFusion array (java vector) or the solution you gave with the toArray() method i allways get the same error:

     

    Cannot perform web service invocation Hello.

    The fault returned when invoking the web service operation is:

    ''java.lang.IlligalArgumentException: argument type mismatch

    Thanks. I got that. I am now talking about the error you get when you do:

     

    <cfscript>

         text = toString("Hello,World").split(",");

    </cfscript>

     

    <cfinvoke method="Hello"

      webservice="http://localhost/Service1.asmx?wsdl"

      returnvariable="response">

         <cfinvokeargument name="array" value="#text#" />

    </cfinvoke>

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 16, 2012 6:32 AM   in reply to Rockit8

    Thanks.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 16, 2012 8:04 AM   in reply to Rockit8

    I can now fully appreciate the extent of the problem. I have just created a test web service, and checked out the signature of the function in the generated stub(String array). But ColdFusion insists on a struct in the call!

     

    Message was edited by: BKBK

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 16, 2012 9:16 AM   in reply to Rockit8
    I was playing with the wsdl2java arguments and according to the documentation this one was worth trying:
    -w or --wrapArrays: Prefers building beans to straight arrays for wrapped XML array types. This switch is not in included in the Axis documentation.

     

    No idea if it will work, but I would think you would want the opposite.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 16, 2012 10:56 AM   in reply to Rockit8

    To clarify, I meant try the nowrap option.  If that does not work, then yes you may be out of luck. I think there is a flag in Axis 2, which obviously does not help here since CF uses Axis 1.x. 

     

    Message was edited by: -==cfSearching==-

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 17, 2012 12:07 AM   in reply to Rockit8

    Rockit8 wrote:

     

    Yes..that didnt work...made no difference. The opposite would be nice but as far as I know there isnt one.

    Did you apply my earlier suggestion, refreshWSDL = "yes", to suppress the use of caching? I expect the following combination to work:

     

    refreshwsdl="yes" wsdl2JavaArgs="nowrapped"

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 17, 2012 3:43 AM   in reply to Rockit8

    In my web service test, the following call works as expected! I am looking into it to see if this is by accident or by design.

     

    <cfscript>

         strArray = toString("Hello,World").split(",");

    </cfscript>

     

    <cfinvoke method="myFunc"

      webservice="http://127.0.0.1:8500/workspace/cf_proj/ws_complexTypes/Test.cfc?wsdl"

      returnvariable="response" refreshwsdl="true" wsdl2JavaArgs="nowrapped" >

         <cfinvokeargument name="arr" value="#strArray#" />

    </cfinvoke>

     

    <cfdump var = "#response#">

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 17, 2012 5:14 AM   in reply to Rockit8

    Rockit8 wrote:

     

    How is your "myfunc" method described in the wsdl? (post the equivalent of what i posted above in your webservice wsdl).

    <xs:element name="myFunc">

        <xs:complexType>

            <xs:sequence>

                <xs:element maxOccurs="unbounded" minOccurs="0" name="arr" nillable="true" type="xs:anyType"/>

            </xs:sequence>

        </xs:complexType>

    </xs:element>

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 17, 2012 10:41 AM   in reply to Rockit8

    so the only difference between what you are using and what i am using is the webservice technology...you are using coldfusion, i am using .net.

     

    True, but that is the key. Since there is no direct mapping of the .NET ArrayOfString class in Axis, it is treated as a structure in CF. Just like any other custom/complex type.

     

    Makes sense...my wsdl is enforcing the ArrayOf<type_name>...

     

    So did you ultimately change anything .. or just leave it as ArrayOfString? (Though that is a  bit of a misnomer imo, since it is a class not an array.)

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 18, 2012 7:39 AM   in reply to Rockit8

    As said before, the transformation of a CF array to the ArrayOf<Type_name> can be one dynamically so i think i'll take that aproach.

    Okay, so ultimately you just went with the original code. Simple enough.

     
    |
    Mark as:
  • Currently Being Moderated
    Dec 17, 2012 5:29 PM   in reply to Rockit8

    Cool, how did you come up with root.string?  Trial and error??  I would love to know why root.string works.

     
    |
    Mark as:
  • Currently Being Moderated
    Dec 17, 2012 11:09 PM   in reply to henrylearn2rock

    henrylearn2rock wrote:

     

    Cool, how did you come up with root.string?  Trial and error??  I would love to know why root.string works.

    Your question seems irrelevant to this thread. Create your own thread, and you will surely get suggestions.

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points