Issues when calling a Coldfusion web services with optional arguments

 Friday January 28, 2011  ·  2186 views  ·  2 comments
I ran into several interesting issues the other day while unit testing a webservice method that had optional arguments. Most of the problems spawned from wrong information in the docs, but it also uncovered some legitimate bugs that I wanted to share in case anyone encountered the same issues.

For context, the web service and web service client I was testing with were both created in Coldfusion using <cfcomponent> for the service and <cfinvoke> to call it. Normally I would use the createObject("webservice", wsdlurl) approach when calling a remote service, but that turned out not to work at all when you are dealing with methods with optional arguments.

Here are some of the issues I ran into and the works arounds for them:

The "value" attribute for <cfinvokeargument> is not really required
In the documentation for <cfinvokeargument>, it lists the "value" attribute as being a required field. This is partially correct depending on whether or not you close out the tag. If you do close the tag you can successfully omit the attribute, but if you forget, the compiler will catch it and complain.
Being able to not supply the "value" attribute is important, it gives us the ability to work around the next issue and ultimately supply optional arguments in our calls.

<cfinvokeargument> will pass values even if you tell it not to
When you are calling a web service using <cfinvoke>, Coldfusion makes you declare all of the arguments defined by the method (required or optional) using the <cfinvokeargument> tag. It seems counter-intuitive that you would have to list optional arguments when you have no plans to send them, but thats the way it is. CF however, provides the "omit='true'" attribute to let you indicate which of those parameters should be ignored when making the call.

If you follow the docs and provide a "value" attribute, Coldfusion will ignore the "omit='true'" attribute and send what ever is in the "value" attribute with the call. For example:
Not all arguments can be optional...by default
The way Coldfusion handles optional arguments as a remote service is that it allows the calling client to pass in a null value. In a document/literal or rpc/encoded WSDL description, an element can accept null unless it specifies "nillable='false'". The generated WSDLs from Coldfusion do not use "nillable='false'" or "minOccurs='0'" which instructs the client that they must include the parameter and that it is ok to pass in a null value.

The problem however is that "numeric" or "boolean" argument types that are optional will throw an "Illegal Argument Exception" when being called by a client who is trying to explicitly pass in null.

To get around this, you must copy the generated WSDL from your service and explicitly add the "minOccurs='0'" attribute to the optional argument elements that are of type "numeric" or "boolean" and then point to that in your <cfinvoke> statement. Take the following component for example: When you navigate to it's WSDL, ie. http://localhost/MyService.cfc?wsdl, you get the following which includes this snippet for the argument definitions of our 'test' method: Modify this WSDL to include "minOccurs='0'" on the numeric and boolean argument: Save it locally (ie modified.wsdl.xml), and then point to it when you make your call:
I was able to confirm the behavior I described above in both CF9 and CF8 running on Windows boxes. There was already a bug filed for the incorrect documentation and faulty "omit" attribute behavior on <cfinvokeargument> (#85534), but I ended up submitting a bug for the issues in passing null to "numeric" and "boolean" types (#86000). Hopefully these issues get resolved or at least have the documentation updated to reflect the true behavior of the tag.

Comments




  • SOAP web services in ColdFusion can be easy... they can also be a nightmare. I've started using JSON for pretty much all of my CF web service stuff... it's made life so much easier.



  • Very much agreed Ben. I've run into many situations where it turns from something simple to a "this is way more complicated than it needs to be" type of situation (ie. having to support or send optional arguments).

 

Leave Feedback


Name


Email
Email will not be displayed

Website
( Optional )

Feedback

Post your feedback, HTML will not be rendered, only plain text.


Security

Answer the math problem below.
= 
Subscribe
Receive emails when others submit comments