ColdFusion and WDDX

Contact Us or call 1-877-932-8228
ColdFusion and WDDX

ColdFusion and WDDX

WDDX stands for Web Distributed Data Exchange. It is an XML format for exchanging data between programming languages and across the web. Although it is not a standard format, there are WDDX implementations for JavaScript, PHP, Perl, ASP, and Java as well as ColdFusion. The following diagram shows how WDDX works.

<cfwddx>

The <cfwddx> tag is used to to convert ColdFusion structures to WDDX and WDDX to ColdFusion structures. It can also convert ColdFusion structures and WDDX strings to JavaScript objects. The tag's attributes are shown below:

<cfwddx> Attributes
Parameter Description
action Required. Possible values are:
  • cfml2wddx: converts CFML to WDDX
  • wddx2cfml: converts WDDX to CFML
  • cfml2js: converts CFML to JavaScript
  • wddx2js: converts WDDX to JavaScript
input Required. The value to convert.
output Required if action is "wddx2cfml". Variable name of output object. If action is not "wddx2cfml" and output is omitted, the result is output as text.
topLevelVariable Required when converting to JavaScript. Variable name of JavaScript WddxRecordset object, which can be manipulated with functions made available by the wddx.js file.
useTimeZoneInfo Optional. Default is "yes". Attempts to convert time between server and client.
validate Optional. Default is "no". Applicable when converting from WDDX. If "yes", WDDX is validated before conversion and an error is thrown if it is invalid.

The wddx.js File

The wddx.js file, which is stored in CFIDE/scripts/wddx.js, makes it easy to convert JavaScript objects to WDDX by creating a new object of the WddxSerializer class and calling its serialize() method.

Below we will build a simple application for creating and saving a list of resources to share among websites.

  1. First, we will build the original list as a ColdFusion structure, which we will make available as WDDX for consumption.
  2. Next, we will show how to consume the WDDX produced in step 1 with another ColdFusion page.
  3. Then we will show how to consume the WDDX produced in step 1 with JavaScript and how to modify it, save the content in a form field, and submit it to a ColdFusion page for processing.
  4. Then we will show how to save the modified WDDX content in a file.
  5. Then we will show how to read the WDDX from the file and make it available for consumption.
  6. Finally, we show how to consume that WDDX content with JavaScript. This is the same as step 3, except that it gets the WDDX from a different source.

Code Sample:

XML/Demos/WddxLinks.cfm
<cfcontent type="text/xml">
<cfset objWddx = StructNew()>

<cfset objWddx.Links = ArrayNew(1)>
<cfset i = ArrayLen(objWddx.Links)+1>
<cfset objWddx.Links[i] = StructNew()>
<cfset objWddx.Links[i].Title = "Webucator">
<cfset objWddx.Links[i].URL = "http://www.webucator.com">
<cfset objWddx.Links[i].Description = "Webucator provides customized onsite technical training.">
<cfset objWddx.Links[i].Categories = ArrayNew(1)>
<cfset ArrayAppend(objWddx.Links[i].Categories,"Training")>
<cfset ArrayAppend(objWddx.Links[i].Categories,"IT")>
<cfset ArrayAppend(objWddx.Links[i].Categories,"Computers")>

<cfset i = ArrayLen(objWddx.Links)+1>
<cfset objWddx.Links[i] = StructNew()>
<cfset objWddx.Links[i].Title = "Adobe">
<cfset objWddx.Links[i].URL = "http://www.adobe.com">
<cfset objWddx.Links[i].Description = "Adobe develops computer software products and technologies that enable users to express and use information across all print and electronic media.">
<cfset objWddx.Links[i].Categories = ArrayNew(1)>
<cfset ArrayAppend(objWddx.Links[i].Categories,"Software")>
<cfset ArrayAppend(objWddx.Links[i].Categories,"IT")>
<cfset ArrayAppend(objWddx.Links[i].Categories,"Computers")>

<cfset i = ArrayLen(objWddx.Links)+1>
<cfset objWddx.Links[i] = StructNew()>
<cfset objWddx.Links[i].Title = "Microsoft">
<cfset objWddx.Links[i].URL = "http://www.microsoft.com">
<cfset objWddx.Links[i].Description = "Microsoft offers a wide range of software, services, and Internet technologies for personal and business computing.">
<cfset objWddx.Links[i].Categories = ArrayNew(1)>
<cfset ArrayAppend(objWddx.Links[i].Categories,"Software")>
<cfset ArrayAppend(objWddx.Links[i].Categories,"IT")>
<cfset ArrayAppend(objWddx.Links[i].Categories,"Computers")>

<cfset i = ArrayLen(objWddx.Links)+1>
<cfset objWddx.Links[i] = StructNew()>
<cfset objWddx.Links[i].Title = "Google">
<cfset objWddx.Links[i].URL = "http://www.google.com">
<cfset objWddx.Links[i].Description = "Google is the leading search engine.">
<cfset objWddx.Links[i].Categories = ArrayNew(1)>
<cfset ArrayAppend(objWddx.Links[i].Categories,"Search")>
<cfset ArrayAppend(objWddx.Links[i].Categories,"IT")>

<cfwddx action="cfml2wddx" input="#objWddx#">
            

This file simply creates a ColdFusion structure holding the following information about web resources:

  • Link Title (string)
  • Link URL (string)
  • Link Description (string)
  • Link Categories (array)

It then converts the structure to WDDX and outputs it to the browser using the <cfwddx> tag.

Code Sample:

XML/Demos/WddxConsume.cfm
<cfset thisPage = "#CGI.SERVER_NAME##CGI.SCRIPT_NAME#">
<cfset arrFileParts = ListToArray(CGI.SCRIPT_NAME,"/")>
<cfset ArrayDeleteAt(arrFileParts,ArrayLen(arrFileParts))>
<cfset path = ArrayToList(arrFileParts,"/")>
<cfset pathToWddx = "http://#CGI.SERVER_NAME#:#CGI.SERVER_PORT#/#path#/WddxLinks.cfm">
<cfhttp method="get" url="#pathToWddx#">

<cfwddx action="wddx2cfml" input="#cfhttp.FileContent#" output="objWddx" validate="yes">
<html>
<head>
<title>Links Page</title>
</head>

<body>
<cfset arrLinks = objWddx.links>
<cfset linkCat = "Software">
<ul>
<cfoutput>
<cfloop from="1" to="#ArrayLen(arrLinks)#" index="i">
	<cfset strCats = ArrayToList(arrLinks[i].Categories)>
	<cfif ListFind(strCats,linkCat)> 
	<li><a href="#arrLinks[i].URL#">#arrLinks[i].Title#</a> - #arrLinks[i].Description#</li>
	</cfif>
</cfloop>
</cfoutput>
</ul>
</body>
</html>

This file uses the <cfhttp> tag to read in the WddxConsume.cfm file. It then uses the <cfwddx> tag to convert the file's content to a ColdFusion structure and loops through the output producing links that are included in the "Software" category.

Code Sample:

XML/Demos/WddxConsume-js.cfm
<cfset thisPage = "#CGI.SERVER_NAME##CGI.SCRIPT_NAME#">
<cfset arrFileParts = ListToArray(CGI.SCRIPT_NAME,"/")>
<cfset ArrayDeleteAt(arrFileParts,ArrayLen(arrFileParts))>
<cfset path = ArrayToList(arrFileParts,"/")>
<cfset pathToWddx = "http://#CGI.SERVER_NAME#:#CGI.SERVER_PORT#/#path#/WddxLinks.cfm">
<cfhttp method="get" url="#pathToWddx#">

<html>
<head>
<title>Links Page</title>
<script language="javascript" src="wddx.js"></script>
<script language="javascript">
	<cfwddx action="wddx2js" input="#cfhttp.FileContent#" toplevelvariable="objLinks">
	
	              var serializer = new WddxSerializer();
	function addLink(FORM)
	{
		var arrLen = objLinks.links.length;
		objLinks.links[arrLen] = new Object();
		objLinks.links[arrLen]["title"] = FORM.title.value;
		objLinks.links[arrLen]["description"] = FORM.description.value;
		objLinks.links[arrLen]["url"] = FORM.url.value;
		objLinks.links[arrLen]["categories"] = FORM.categories.value.split(",");
		document.forms[0].strWddx.value=serializer.serialize(objLinks);
		addListItem(objLinks.links[arrLen]["title"]);
	}
	
	function addListItem(TEXT)
	{
		var li = document.createElement("li");
		var liText = document.createTextNode(TEXT);
		list.appendChild(li);
		li.appendChild(liText);
	}
	
	var list;
	window.onload = function() {
		document.forms[0].title.focus();
		document.forms[0].strWddx.value=serializer.serialize(objLinks);
		list=document.getElementById("listLinks");
		for (i in objLinks.links)
		{
			addListItem(objLinks.links[i].title);
		}
	}
</script>
</head>
<body>
<form method="post" action="SaveLinks.cfm">
	<input type="hidden" name="strWddx" value="">
	<table>
		<tr>
			<td>Title:</td>
			<td><input type="text" size="50" name="title"></td>
		</tr>
		<tr>
			<td>URL:</td>
			<td><input type="text" size="50" name="url"></td>
		</tr>
		<tr valign="top">
			<td>Description:</td>
			<td><textarea name="description" cols="50" rows="3"></textarea></td>
		</tr>
		<tr valign="top">
			<td>Categories:</td>
			<td>
				Must be comma-delimited<br>
				<textarea name="categories" cols="50" rows="2"></textarea>
			</td>
		</tr>
		<tr>
			<td colspan="2" align="right">
				<input type="button" value="Add Link" onClick="addLink(this.form)">
				<input type="submit" value="Save Links">
			</td>
		</tr>
	</table>
</form>
<h1>Links</h1>
<ul id="listLinks"></ul>
</body>
</html>

This file also uses the <cfhttp> tag to read in the WddxConsume.cfm file. Inside HTML <script> tags, it uses the <cfwddx> tag to create the JavaScript necessary to represent the WDDX as a JavaScript object. When the page finishes loading, JavaScript is used to create list items showing the titles of the different links. An HTML form is provided for adding new links. When the "Add Link" button is clicked, a new link is added to the JavaScript object and the WDDX is stored in the hidden field, strWddx. When the "Save Links" submit button is pressed, the form is submitted to the SaveLinks.cfm page.

Code Sample:

XML/Demos/SaveLinks.cfm
<html>
<head>
<title>WDDX: Save Links</title>
</head>
<body>
	<cftry>
		<cffile action="write" output="#FORM.strWddx#" file="#ExpandPath('links.xml')#" nameconflict="overwrite">
		Links saved.
		<cfcatch type="any">
			Could not save links: <cfoutput>#cfcatch.Message#</cfoutput>
		</cfcatch>
	</cftry>
</body>
</html>

This file simply uses <cffile> to save the WDDX string to a file (links.xml).

Code Sample:

XML/Demos/WddxLinksFromFile.cfm
<cftry>
	<cfcontent type="text/xml">
	<cffile action="read" file="#ExpandPath('links.xml')#" variable="strWddx">
	
	<cfoutput>#strWddx#</cfoutput>
	<cfcatch type="any">
		<cfcontent type="text/html">
		<cfoutput>#cfcatch.Message#</cfoutput>
	</cfcatch>
</cftry>

This file uses <cffile> to read in links.xml and outputs the result.

Code Sample:

XML/Demos/WddxConsume-js2.cfm
<cfset thisPage = "#CGI.SERVER_NAME##CGI.SCRIPT_NAME#">
<cfset arrFileParts = ListToArray(CGI.SCRIPT_NAME,"/")>
<cfset ArrayDeleteAt(arrFileParts,ArrayLen(arrFileParts))>
<cfset path = ArrayToList(arrFileParts,"/")>
<cfset pathToWddx = "http://#CGI.SERVER_NAME#:#CGI.SERVER_PORT#/#path#/WddxLinksFromFile.cfm">
<cfhttp method="get" url="#pathToWddx#">


---- C O D E   O M I T T E D ----

This file is almost the same as WddxConsume-js.cfm. It just reads from WddxLinksFromFile.cfm rather than WddxLinks.cfm.

WDDX vs. Web Services

Like WDDX, web services provide a mechanism for different applications to share data. Web services, however, do much more than that. They provide a mechanism for sharing objects, making their methods invokable over distributed systems. The scope of WDDX is much smaller. WDDX simply provides a way of sharing data between program languages. It provides no built-in way for one system to invoke processes on another system.