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

Invoke webservice with complex types

Guest
Apr 13, 2012 Apr 13, 2012

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.

9.5K
Translate
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

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>

Translate
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

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.

Translate
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

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>

Translate
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

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

Translate
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

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>

Translate
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

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.

Translate
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

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. 

Translate
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

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.

Translate
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

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.

Translate
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

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.

Translate
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

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

Translate
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

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>

Translate
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

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>

Translate
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

Thanks.

Translate
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

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

Translate
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

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

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

Translate
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

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

Translate
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

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

Translate
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

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"

Translate
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

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

Translate
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

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

Translate
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

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.

Translate
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

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>

Translate
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