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.
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>
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.
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>
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
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>
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.
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.
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.
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.
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.
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
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>
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>
Copy link to clipboard
Copied
Thanks.
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
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
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.
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.
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==-
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"
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..
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#">
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.
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>