Consuming web services

ColdFusion provides two methods for consuming web services. The method that you choose depends on your ColdFusion programming style and application.

The following table describes these methods:
Method
CFML operator
Description
CFScript
CreateObject()
Consumes a web service from within a CFScript block
CFML tag
cfinvoke
Consumes a web service from within a block of CFML code

One important consideration is that all consumption methods use the same underlying technology and offer the same performance.

About the examples in this section

The examples in this section reference the BabelFish web service from AltaVista. BabelFish can translate string up to 5 KB in length from one language to another. You can read the WSDL file for this web service in "Reading a WSDL file".

If you add the BabelFish web service in Dreamweaver MX, you see the following description of it in the Application panel.

The BabelFish web service displayed in Dreamweaver MX

For information on adding a web service in Dreamweaver, see "Viewing a WSDL file using Dreamweaver MX". For more information on BabelFish, see http://babelfish.altavista.com/.

Passing parameters to a web service

One type of information in the WSDL file defines the web service operations and the input and output parameters of each operation, including the data type of each parameter. If you register the web service in Dreamweaver MX, as shown in the previous section, you see that the data type of both input parameters is string.

The following example shows a portion of the WSDL file for the BabelFish web service:

<message name="BabelFishRequest"> 
  <part name="translationmode" type="xsd:string" /> 
  <part name="sourcedata" type="xsd:string" /> 
</message> 
<message name="BabelFishResponse"> 
  <part name="return" type="xsd:string" /> 
</message> 
<portType name="BabelFishPortType"> 
  <operation name="BabelFish"> 
    <input message="tns:BabelFishRequest" /> 
    <output message="tns:BabelFishResponse" /> 
  </operation> 
</portType> 

The operation name used in the examples in this section is BabelFish. This operation takes a single input parameter defined as a message of type BabelFishRequest.

You can see that the message BabelFishRequest contains two string parameters: translationmode and sourcedata. When you call the BabelFish operation, you pass both parameters as input.

Handling return values from a web service

Web service operations often return information back to your application. You can determine the name and data type of returned information by examining the WSDL file for the web service.

If you register the web service in Dreamweaver MX, you see that the data type of the return value is string.

The following example shows a portion of the WSDL file for the BabelFish web service:

<message name="BabelFishRequest"> 
  <part name="translationmode" type="xsd:string" /> 
  <part name="sourcedata" type="xsd:string" /> 
</message> 
<message name="BabelFishResponse"> 
  <part name="return" type="xsd:string" /> 
</message> 
<portType name="BabelFishPortType"> 
  <operation name="BabelFish"> 
    <input message="tns:BabelFishRequest" /> 
    <output message="tns:BabelFishResponse" /> 
  </operation> 
</portType> 

The operation BabelFish returns a message of type BabelFishResponse. The message statement in the WSDL file defines the BabelFishResponse message as containing a single string parameter named return.

Using cfinvoke to consume a web service

This section describes how to consume a web service using the cfinvoke tag. With the cfinvoke tag, you reference the WSDL file and invoke an operation on the web service with a single tag.

The cfinvoke tag has the following syntax:

<cfinvoke 
  webservice = "URLtoWSDL" 
  method = "operationName"
  inputParam1 = "val1"
  inputParam2 = "val2"
  ...
  returnVariable = "varName"
>

where:

To access a web service using cfinvoke:

  1. Create a ColdFusion page with the following content:
    <cfinvoke 
      webservice = "http://www.xmethods.net/sd/2001/BabelFishService.wsdl"
      method = "BabelFish"
      translationmode = "en_es" 
      sourcedata = "Hello world, friend"
      returnVariable = "foo">
    <cfoutput>#foo#</cfoutput>
    
  2. Save the page as wscfc.cfm in your web root directory.
  3. View the page in your browser.

    The following string appears in your browser:

    Hola mundo, amigo
    

You can pass parameters to web services using two other mechanisms: the cfinvokeargument tag and the argumentCollection attribute of the cfinvoke tag.

To pass parameters using the cfinvokeargument tag, you write your call to the web service, as the following code shows:

<cfinvoke
  webservice ="http://www.xmethods.net/sd/2001/BabelFishService.wsdl"
  method ="BabelFish"
  returnVariable = "varName" >
    <cfinvokeargument name="translationmode" value="en_es">
    <cfinvokeargument name="sourcedata" value="Hello world, friend">
</cfinvoke>
<cfoutput>#varName#</cfoutput>  

The cfinvokeargument tag is a nested tag of the cfinvoke tag that lets you specify the name and value of a parameter passed to the web service.

You can also use an attribute collection to pass parameters. An attribute collections is a structure where each structure key corresponds to a parameter name and each structure value is the parameter value passed for the corresponding key. The following example shows an invocation of a web service using an attribute collection:

<cfscript>
  stArgs = structNew();
  stArgs.translationmode = "en_es";
  stArgs.sourceData= "Hello world, friend";
</cfscript>

<cfinvoke
  webservice = "http://www.xmethods.net/sd/2001/BabelFishService.wsdl"
  method     = "BabelFish"
  argumentCollection = "#stArgs#"
  returnVariable = "varName" > 
<cfoutput>#varName#</cfoutput>  

In this example, you create the structure in a CFScript block, but you can use any ColdFusion method to create the structure.

Using CFScript to consume a web service

The example in this section uses CFScript to consume a web service. In CFScript, you use the CreateObject function to connect to the web service. After connecting, you can make requests to the service. The CreateObject function has the following syntax:

webServiceName = CreateObject("webservice", "URLtoWSDL")

where URLtoWSDL specifies the URL to the WSDL file for the web service.

After creating the web service object, you can call operations of the web service using dot notation, in the following form:

webServiceName.operationName(inputVal1, inputVal2, ... )

You can handle return values from web services by writing them to a variable, as the following example shows:

resultVar = webServiceName.operationName(inputVal1, inputVal2, ... );

Or, you can pass the return values directly to a function, such as the writeOutput function, as follows:

writeoutput(webServiceName.operationName(inputVal1, inputVal2, ...) );

To access a web service from CFScript:

  1. Create a ColdFusion page with the following content:
    <cfscript>
      ws = CreateObject("webservice", 
            "http://www.xmethods.net/sd/2001/BabelFishService.wsdl");
      xlatstring = ws.BabelFish("en_es", "Hello world, friend");
      writeoutput(xlatstring);
    </cfscript>
    
  2. Save the page as wscfscript.cfm in your web root directory.
  3. View the page in your browser.

    The following string appears in your browser:

    Hola mundo, amigo
    

You can also use named parameters to pass information to a web service. The following example performs the same operation as above, except that it uses named parameters to make the web service request:

<cfscript>
  ws = createObject("webservice",
"http://www.xmethods.net/sd/2001/BabelFishService.wsdl");
  xlatstring = ws.BabelFish(translationmode = "en_es", 
          sourcedata = "Hello world, friend");
</cfscript>
<cfoutput>#xlatstring#</cfoutput>

Calling web services from a Flash client

The Flash Remoting service lets you call ColdFusion pages from a Flash Client, but it does not let you call web services directly. To call web services from a Flash client, you can use Flash Remoting to call a ColdFusion component that calls the web service. The Flash client can pass input parameters to the component, and the component can return to the Flash client any data returned by the web service.

For more information on Flash Remoting, see Chapter 29, "Using the Flash Remoting Service".

Catching errors when consuming web services

Web services might throw errors, including SOAP faults, during processing that you can catch in your application. If uncaught, these errors propagate to the browser.

To catch errors, you specify an error type of application to the ColdFusion cfcatch tag, as the following example shows:

<cftry>
  Put your application code here ...
  <cfcatch type="application">
    <!--- Add exception processing code here ... --->
  </cfcatch>
  .
  .
  .
  <cfcatch type="Any">
    <!--- Add exception processing code appropriate for all other 
exceptions here ... --->
  </cfcatch>
</cftry>

For more information on error handling, see Chapter 14, "Handling Errors".

Handling inout and out parameters

Some web services define inout and out parameters. You use out parameters to pass a placeholder for a return value to a web service. The web service then returns its result by writing it to the out parameter. Inout parameters let you pass a value to a web service and lets the web service return its result by overwriting the parameter value.

The following example shows a web service that takes as input an inout parameter containing a string and writes its results back to the string:

<cfset S="foo">
<cfscript>
  ws=createobject("webservice", "URLtoWSDL")
  ws.modifyString("S");
<cfscript>
<cfoutput>#S#</cfoutput>

Even though this web service takes as input the value of S, because you pass it as an inout parameter you do not enclose it in pound signs.

Note:   ColdFusion supports the use of inout and out parameters to consume web services. However, ColdFusion does not support inout and out parameters when creating web services for publication.

Configuring web services in the ColdFusion Administrator

The ColdFusion Administrator lets you register web services so that you do not have to specify the entire WSDL URL when you reference the web service.

Note:   The first time you reference a web service, ColdFusion automatically registers it in the Administrator.

For example, the following code references the URL to the BabelFish WSDL file:

<cfscript>
  ws = CreateObject("webservice",
"http://www.xmethods.net/sd/2001/BabelFishService.wsdl");
  xlatstring = ws.BabelFish("en_es", "Hello world, friend");
  writeoutput(xlatstring);
</cfscript>

If you register the BabelFish web service in the ColdFusion Administrator using, for example, the name wsBabel, you could then reference the web service as follows:

<cfscript>
  ws = CreateObject("webservice", "wsBabel");
  xlatstring = ws.BabelFish("en_es", "Hello world, friend");
  writeoutput(xlatstring);
</cfscript>

Not only does this enable you to shorten your code, registering a web service in the ColdFusion Administrator lets you change a web service's URL without modifying your code. So, if the BabelFish web service moves to a new location, you only update the administrator setting; not your application code.

For more information, see the online help in the ColdFusion Administrator.

Data conversions between ColdFusion and WSDL data types

A WSDL file defines the input and return parameters of an operation, including data types. For example, the BabelFish web service contains the following definition of input and return parameters:

<message name="BabelFishRequest"> 
    <part name="translationmode" type="xsd:string" /> 
    <part name="sourcedata" type="xsd:string" /> 
  </message> 
  <message name="BabelFishResponse"> 
    <part name="return" type="xsd:string" /> 
</message> 

As part of consuming web services, you must understand how ColdFusion converts WSDL defined data types to ColdFusion data types. The following table shows this conversion:
ColdFusion data type
WSDL data type
numeric
SOAP-ENC:double
boolean
SOAP-ENC:boolean
string
SOAP-ENC:string
array
SOAP-ENC:Array
binary
xsd:base64Binary
date
xsd:dateTime
void (operation returns nothing)

struct
complex type

For many of the most common data types, such as string and numeric, a WSDL data type maps directly to a ColdFusion data type. For complex WSDL data types, the mapping is not as straight forward. In many cases, you map a complex WSDL data type to a ColdFusion structure. For more information on handling complex data types, see "Handling complex data types".

Consuming ColdFusion web services

Your application might consume web services created in ColdFusion. You do not have to perform any special processing on the input parameters or return values because ColdFusion handles data mappings automatically when consuming a ColdFusion web service.

For example, when ColdFusion publishes a web service that returns a query, or takes a query as an input, the WSDL file for that service lists its data type as QueryBean. However, a ColdFusion application consuming this web service can pass a ColdFusion query object to the function as an input, or write a returned QueryBean to a ColdFusion query object.

Note:   For a list of how ColdFusion data types map to WSDL data types, see "Data conversions between ColdFusion and WSDL data types".

The following example shows a ColdFusion component that takes a query as input and echoes the query back to the caller:

<cfcomponent>
  <cffunction name='echoQuery' returnType='query' access='remote'>
    <cfargument name='input' type='query'>
    <cfreturn #arguments.input#>
  </cffunction>
</cfcomponent>

If you add this web service in Dreamweaver MX, you see the following description of it in the Application panel:

The echotypes web service shown in Dreamweaver MX

Note:   This figure assumes that you create a web component named echotypes.cfc that contains the echoQuery function definition shown above, and write echotypes.cfc to your web root directory.

In the WSDL file for the echotypes.cfc component, you see the following definitions that specify the type of the function's input and output as QueryBean:

<wsdl:message name="echoQueryRequest">
  <wsdl:part name="input" type="tns1:QueryBean"/>
</wsdl:message>
<wsdl:message name="echoQueryResponse">
  <wsdl:part name="return" type="tns1:QueryBean"/>
</wsdl:message>

Since ColdFusion automatically handles mappings to ColdFusion data types, you can call this web service as the following example shows:

<head>
<title>Passing queries to web services</title>
</head>
<body>
<cfquery name="GetEmployees" datasource="CompanyInfo">
  SELECT FirstName, LastName, Salary
  FROM Employee
</cfquery>

<cfinvoke 
  webservice = "http://localhost/echotypes.cfc?wsdl"
  method = "echoQuery"
  input="#GetEmployees#"
  returnVariable = "returnedQuery">

<cfoutput>
  Is returned result a query? #isQuery(returnedQuery)# <br><br>
</cfoutput>

<cfoutput query="returnedQuery">
  #FirstName#
  #LastName#
  #Salary#<br>
</cfoutput>
</body>

Comments