• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Invoke webservice with complex types

Guest
Apr 13, 2012 Apr 13, 2012

Copy link to clipboard

Copied

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.

Views

8.9K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 14, 2012 Apr 14, 2012

Copy link to clipboard

Copied

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>

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

Hi BFBK, thanks for your reply.

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

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

Thanks.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

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>

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

You are right, i was looking just at the basic <cfdump.../>

The thing is, by decompiling the java stubs generated by the wsdl2java i can see this:

public abstract interface Service1Soap extends Remote
{

  public abstract String Hello(ArrayOfString paramArrayOfString)
    throws RemoteException;
}

He is expecting a structure of the type ArrayOfString. Looking at this class i can see the following property:

public String[] string;

So this is basically the reason i created the structure and property with names that match this description in the first place... this is want i wanted to avoid.

Of course i can do this dinamically for some cases but if there is an out-of-the-box method to do this i would like to know.

Regarding the hello signature...its a .Net webservice and the method has the following signature:

public string Hello(string[] array);

After looking at the WSDL i think there is not mutch i can do to avoid this:

<s:element name="Hello">

     <s:complexType>

          <s:sequence>

               <s:element minOccurs="0" maxOccurs="1" name="array" type="tns:ArrayOfString"/>

          </s:sequence>

     </s:complexType>

</s:element>

     <s:complexType name="ArrayOfString">

          <s:sequence>

          <s:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="s:string"/>

     </s:sequence>

</s:complexType>

Thanks.

Message was edited by: Rockit8

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

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>

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

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

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.

Thanks.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

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. 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

BKBK wrote:

Does it work?

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

BKBK wrote:


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.

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...

Lets forget about the generic part...if there is a way to invoke that method without creating the "root structure" that solves my problem.

Thanks.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

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>

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

BKBK wrote:

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>

Its the same argument type mismatch error.

It only works if you change it to this:

<cfscript>

     text = toString("Hello,World").split(",");
      root.string = text; //create structure and property

</cfscript>

<cfinvoke method="Hello"

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

  returnvariable="response">

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

</cfinvoke>

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

Thanks.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

Yes, he allways creates a struct wrapping the arrays.

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.

But the proxy generation was exactly the same and the error still occurred.

Just because i'm curious...you created a webservice using .net or other technology?

Message was edited by: Rockit8

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Apr 16, 2012 Apr 16, 2012

Copy link to clipboard

Copied

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==-

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 17, 2012 Apr 17, 2012

Copy link to clipboard

Copied

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"

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Apr 17, 2012 Apr 17, 2012

Copy link to clipboard

Copied

Hi

The "--nowrapped" arg changes the way the wsdl is generated but not in the way i wanted, using the same method as above what it creates in the java is this:

public abstract HelloResponse Hello(hello paramHello)

    throws RemoteException;

He creates a new class that wraps the request and response parameters:

public class hello

  implements Serializable

{

[...]

  private ArrayOfString array;

[...]

So the --nowrap actually works like one more level of wrapping..

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 17, 2012 Apr 17, 2012

Copy link to clipboard

Copied

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#">

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Apr 17, 2012 Apr 17, 2012

Copy link to clipboard

Copied

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

I copy-pasted your code, changed the webservice and got the same error...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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 17, 2012 Apr 17, 2012

Copy link to clipboard

Copied

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>

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources
Documentation