Adobe ColdFusion 8

Handling complex data types

When dealing with web services, handling complex types falls into the following categories:

  • Mapping the data types of a web service to consume to ColdFusion data types
  • Understanding how clients will reference your ColdFusion data types when you publish a web service

This section describes both categories.

Consuming web services that use complex data types

The following table shows how WSDL data types are converted to ColdFusion data types:

ColdFusion data type

WSDL data type

numeric

SOAP-ENC:double

boolean

SOAP-ENC:boolean

string

SOAP-ENC:string

array

SOAP-ENC:Array

numeric

SOAP-ENC:float

binary

xsd:base64Binary

date

xsd:dateTime

void (operation returns nothing)

 

structure

complex type

This table shows that complex data types map to ColdFusion structures. ColdFusion structures offer a flexible way to represent data. You can create structures that contain single-dimension arrays, multi-dimensional arrays, and other structures.

The ColdFusion mapping of complex types to structures is not automatic. You have to perform some processing on the data in order to access it as a structure. The next sections describe how to pass complex types to web services, and how to handle complex types returned from web services.

Passing input parameters to web services as complex types

A web service can take a complex data type as input. In this situation, you can construct a ColdFusion structure that models the complex data type, then pass the structure to the web service.

For example, the following excerpt from a WSDL file shows the definition of a complex type named Employee:

<s:complexType name="Employee"> 
 <s:sequence> 
   <s:element minOccurs="1" maxOccurs="1" name="fname" type="s:string" /> 
   <s:element minOccurs="1" maxOccurs="1" name="lname" type="s:string" /> 
   <s:element minOccurs="1" maxOccurs="1" name="active" type="s:boolean" /> 
   <s:element minOccurs="1" maxOccurs="1" name="age" type="s:int" /> 
   <s:element minOccurs="1" maxOccurs="1" name="hiredate" type="s:dateTime" /> 
   <s:element minOccurs="1" maxOccurs="1" name="number" type="s:double" /> 
 </s:sequence> 
</s:complexType>

The Employee data type definition includes six elements, the data type of each element, and the name of each element.

Another excerpt from the WSDL file shows a message definition using the Employee data type. This message defines an input parameter, as the following code shows:

<message name="updateEmployeeInfoSoapIn"> 
    <part name="thestruct" type="s0:Employee" /> 
</message>

A third excerpt from the WSDL file shows the definition of an operation, named updateEmployeeInfo, possibly one that updates the employee database with the employee information. This operation takes as input a parameter of type Employee, as the following code shows:

<operation name="updateEmployeeInfo"> 
    <input message="s0:updateEmployeeInfoSoapIn" /> 
</operation>

To call the updateEmployeeInfo operation, create a ColdFusion structure, initialize six fields of the structure that correspond to the six elements of Employee, and then call the operation, as the following code shows:

<!--- Create a structure using CFScript, then call the web service. --->
<cfscript>
    stUser = structNew();
    stUser.active = TRUE;
    stUser.fname = "John";
    stUser.lname = "Smith";
    stUser.age = 23;
    stUser.hiredate = createDate(2002,02,22);
    stUser.number = 123.321;

    ws = createObject("webservice", "http://somehost/EmployeeInfo.asmx?wsdl");
    ws.updateEmployeeInfo(stUser);
</cfscript> 

You can use structures for passing input parameters as complex types in many situations. However, to build a structure to model a complex type, you have to inspect the WSDL file for the web service to determine the layout of the complex type. This can take some practice.

Handling return values as complex types

When a web service returns a complex type, you can write that returned value directly to a ColdFusion variable.

The previous section used a complex data type named Employee to define an input parameter to an operation. A WSDL file can also define a return value using the Employee type, as the following code shows:

<message name="updateEmployeeInfoSoapOut"> 
    <part name="updateEmployeeInfoResult" type="s0:Employee" /> 
</message>
<operation name="updateEmployeeInfo"> 
    <input message="s0:updateEmployeeInfoSoapIn" /> 
    <output message="s0:updateEmployeeInfoSoapOut" /> 
</operation>

In this example, the operation updateEmployeeInfo takes a complex type as input and returns a complex type as output. To handle the input parameter, you create a structure. To handle the returned value, you write it to a ColdFusion variable, as the following example shows:

<!--- Create a structure using CFScript, then call the web service. --->
<!--- Write the returned value to a ColdFusion variable. --->
<cfscript>
    stUser = structNew();
    stUser.active = TRUE;
    stUser.fname = "John";
    stUser.lname = "Smith";
    stUser.age = 23;
    stUser.hiredate = createDate(2002,02,22);
    stUser.number = 123.321;

    ws = createObject("webservice", "http://somehost/echosimple.asmx?wsdl");
    myReturnVar = ws.echoStruct(stUser);

</cfscript> 

<!--- Output the returned values. --->
<cfoutput>
    <br>
    <br>Name of employee is: #myReturnVar.fname##myReturnVar.lname#
    <br>Active status: #myReturnVar.active#
    <br>Age:#myReturnVar.age#
    <br>Hire Date: #myReturnVar.hiredate#
    <br>Favorite Number: #myReturnVar.number# 
</cfoutput>

You access elements of the variable myReturnVar using dot notation in the same way that you access structure fields. If a complex type has nested elements, in the way a structure can have multiple levels of nested fields, you use dot notation to access the nested elements, as in a.b.c.d, to whatever nesting level is necessary.

However, the variable myReturnVar is not a ColdFusion structure. It is a container for the complex type, but has none of the attributes of a ColdFusion structure. Calling the ColdFusion function isStruct on the variable returns False.

You can copy the contents of the variable to a ColdFusion structure, as the following example shows:

<cfscript>
...
    ws = createObject("webservice", "http://somehost/echosimple.asmx?wsdl");
    myReturnVar = ws.echoStruct(stUser);

    realStruct = structNew();
    realStruct.active = #myReturnVar.active#;
    realStruct.fname = "#myReturnVar.fname#";
    realStruct.lname = "#myReturnVar.lname#";
    realStruct.age = #myReturnVar.age#;
    realStruct.hiredate = #myReturnVar.hiredate#;
    realStruct.number = #myReturnVar.number#;

</cfscript> 

Calling IsStruct on realStruct returns True and you can use all ColdFusion structure functions to process it.

This example shows that ColdFusion variables and structures are useful for handling complex types returned from web services. To understand how to access the elements of a complex type written to a ColdFusion variable, you have to inspect the WSDL file for the web service. The WSDL file defines the API to the web service and will provide you with the information necessary to handle data returned from it.