Web Services and Nulls

With all of the talk about null values today I thought I'd throw my hat in the ring and talk about one other area where null values can be an issue: web services. Some web services may expect null values for empty arguments and others may expect the empty argument to be left out of the request completely. Fortunately ColdFusion has a way of handling this via omit attribute of the <cfinvokeargument> tag.

Let's say you have the following complex type defined in your WSDL:

<complexType name="TypeWithNulls">
   <sequence>
      <element name="nullItem" nillable="true" type="xsd:anyType"/>
      <element name="optionalItem" minOccurs="0" type="xsd:anyType"/>
   </sequence>
</complexType>

The first element, nullItem, can accept null values while the second item is completely optional.

Now let's say you want to pass some query data to this web service, however both of the columns you want to pass are null and represented by empty strings in the ColdFusion query. Your first approach may look something like this:

<cfinvoke webservice="http://someservice" method="someMethod">
   <cfinvokeargument name="nullItem" value="#myQuery.col1#" />
   <cfif Len(myQuery.col2) gt 0>
      <cfinvokeargument name="optionalItem" value="#myQuery.col2#" />
   </cfif>
</cfinvoke>

While this may work for the optional element (I say may because I haven't actually tested this code) this could be an issue for the nillable element, especially if the web service handles null values differently than empty strings.

A better way to call this web service would be to use the omit attribute of the cfinvokeargument tag like so:

<cfinvoke webservice="http://someservice" method="someMethod">
   <cfif Len(myQuery.col1) eq 0>
      <cfinvokeargument name="nullItem" omit="true" />
   <cfelse>
      <cfinvokeargument name="nullItem" value="#myQuery.col1#" />
   </cfif>
   <cfif Len(myQuery.col2) eq 0>
      <cfinvokeargument name="optionalItem" omit="true" />
   <cfelse>
      <cfinvokeargument name="optionalItem" value="#myQuery.col2#" />
   </cfif>
</cfinvoke>

Unfortunately ColdFusion doesn't allow you to do something like this:

<cfinvoke webservice="http://someservice" method="someMethod">
   <cfinvokeargument name="nullItem" value="#myQuery.col1#" omit="#Len(myQuery.col1) eq 0#" />
   <cfinvokeargument name="optionalItem" value="#myQuery.col2#" omit="#Len(myQuery.col2) eq 0#" />
</cfinvoke>

From the ColdFusion documentation:

If you are invoking a web service, you can omit a parameter by setting the omit attribute to "yes". If the WSDL specifies that the argument is nillable, ColdFusion MX sets the associated argument to null. If the WSDL specifies minoccurs=0, ColdFusion MX omits the argument from the WSDL.

Links:

Comments
BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.