ColdFusion sometimes has trouble assembling the inputs to a web service when the parameters to the web service function are complex. I ran into trouble recently when trying to use the findObjects() method of the API-A interface to a Fedora Commons repository.

There is a discussion of this issue in the adobe forums with a good description of ColdFusion’s behavior when preparing parameters for a web service call.

My particular issue was with the findObjects() method of the API-A web service in Fedora Commons. The input parameters are described as follows in the wsdl:

<element name="findObjects">
  <complexType>
    <sequence>
      <element name="resultFields" type="fedora-types:ArrayOfString"/>
      <element name="maxResults" type="xsd:nonNegativeInteger"/>
      <element name="query" type="fedora-types:FieldSearchQuery"/>
    </sequence>
  </complexType>
</element>

I was attempting to invoke the method with the following code originally:

<cfscript>
  resultFields = ListToArray('pid,label');
  maxResults = 100;
  query = StructNew();
  query['terms'] = 'demo';
</cfscript>

<cfobject type="webservice" name="apia"
  webservice="http://localhost:8080/fedora/wsdl?api=API-A"
  username="fedoraAdmin" password="fedoraAdmin">

<cfinvoke webservice="#apia#" method="findObjects"
  returnVariable="fedoraObjects">
  <cfinvokeargument name="resultFields" value="#resultFields#">
  <cfinvokeargument name="maxResults" value="#maxResults#">
  <cfinvokeargument name="query" value="#query#">
</cfinvoke>

But I got an error message saying "Web service operation findObjects with parameters {query={{terms={demo}}},resultFields={[pid, label]},maxResults={100}} cannot be found." when ColdFusion tried to make the web service call. I tried a number of different configurations of the ‘query’ parameter, such as:

<cfscript>
  resultFields = ListToArray('pid,label');
  maxResults = 100;
  query = StructNew();
  query['terms'] = StructNew();
  query['terms'].value = 'demo';
</cfscript>

<cfobject type="webservice" name="apia"
  webservice="http://localhost:8080/fedora/wsdl?api=API-A"
  username="fedoraAdmin" password="fedoraAdmin">

<cfinvoke webservice="#apia#" method="findObjects"
  returnVariable="fedoraObjects">
  <cfinvokeargument name="resultFields" value="#resultFields#">
  <cfinvokeargument name="maxResults" value="#maxResults#">
  <cfinvokeargument name="query" value="#query#">
</cfinvoke>

But still received a similar error message: "Web service operation findObjects with parameters {query={{terms={{VALUE={demo}}}}},resultFields={[pid, label]},maxResults={100}} cannot be found."

The first two input parameters to the web service method seemed simple enough, an array of strings and a non-negative integer. Query was the one represented by a structure with one of two possible keys, ‘terms’ and ‘conditions’, with ‘conditions’ being an array of Condition objects. I just knew the ‘query’ input parameter had to be the problem.

I was wrong. I had the query parameter correct the first time. The problem was with the integer parameter!!

After looking at the code generated by the org.apache.axis.wsdl.WSDL2Java tool and the api docs for the org.apache.axis.types.NonNegativeInteger class, I thought I might try something different with the ‘maxResults’ parameter:

<cfscript>
  resultFields = ListToArray('pid,label');
  maxResults = StructNew();
  maxResults.value = 100;
  query = StructNew();
  query['terms'] = 'demo';
</cfscript>

<cfobject type="webservice" name="apia"
  webservice="http://localhost:8080/fedora/wsdl?api=API-A"
  username="fedoraAdmin" password="fedoraAdmin">

<cfinvoke webservice="#apia#" method="findObjects"
  returnVariable="fedoraObjects">
  <cfinvokeargument name="resultFields" value="#resultFields#">
  <cfinvokeargument name="maxResults" value="#maxResults#">
  <cfinvokeargument name="query" value="#query#">
</cfinvoke>

It didn’t work, but at least I got a new error message this time: “Error converting CFML arguments to Java classes for web service invocation. Unable to create web service argument class org.apache.axis.types.NonNegativeInteger. Often this is because the web service defines an abstract complexType as an input to an operation. You must create an actual instance of this type in Java.” Aha!! Now that’s a MUCH more useful error message - it event suggests a course of action: instantiating the java object myself. So I did that:

<cfscript>
  resultFields = ListToArray('pid,label');
  //maxResults = 100;  NonNegativeInteger = CreateObject('java',
    'org.apache.axis.types.NonNegativeInteger');
  maxResults = NonNegativeInteger.init(100);

  query = StructNew();
  query['terms'] = 'demo';
</cfscript>

<cfobject type="webservice" name="apia"
  webservice="http://localhost:8080/fedora/wsdl?api=API-A"
  username="fedoraAdmin" password="fedoraAdmin">

<cfinvoke webservice="#apia#" method="findObjects"
  returnVariable="fedoraObjects">
  <cfinvokeargument name="resultFields" value="#resultFields#">
  <cfinvokeargument name="maxResults" value="#maxResults#">
  <cfinvokeargument name="query" value="#query#">
</cfinvoke>

And it worked!!!

I took another look at the org.apache.axis.types.NonNegativeInteger\ class. There are a number of overloaded constructors, several with the same number of arguments. I wonder if this was the cause of ColdFusion’s trouble…

Comments

cfSearching

Darn, I wish I had found this entry sooner! I ran into the same problem recently. I took similar steps to troubleshoot it and ultimately came to the same conclusion: I needed to pass an instance of the object. However, I would love to know why CF cannot create an instance of this class. Using the single argument constructors as a guide, I tried passing a String and even a byte array but no joy. If you find out anything more about the cause, or another way around it, please let us know. Thanks for the entry.