Use ColdFusion Function Return Type of XML to Provide XML to Both Spry and Flex
This blog entry discusses how I create a function that queries a database, transforms the query results into XML, and returns the XML in a format that can be used by either Spry (pre-release version 1.3) or Flex 2.0. ColdFusion 7 added a return type of XML (see: ColdFusion 7 documentation). However, I've had to experiment some to get my CFC functions to return XML that can be used by both Spry and Flex 2.0.
My first step is to create a normal CFC function that returns type query and then test the function to ensure I'm getting the data I expect. My next step is to change the return type to xml and transform the query result into an XML format. I use Ray Camden's toXML cfc, which includes several different functions for converting various types (array, structure, list, query) to XML format. The version of toXML that I use can be found here: http://ray.camdenfamily.com/index.cfm/2006/7/13/ToXML-Update
<cffunction name="getPeople" access="remote" returntype="xml" output="false" description="Returns first, last, city, and
presenter id as xml">
<cfset var peopleQry = "">
<cfset var peopleXML = "">
<cfset var parsedPeopleXML = "">
<cfquery name="peopleQry" datasource="#dsn#">
SELECT TOP 50 presenters.presenterID, presenters.firstName as firstName,
presenters.lastName as lastName, presenters.city
FROM presenters
WHERE presenters.presenterid > 5000
</cfquery>
<!---use Ray Camden's toXML CFC to convert the query to an XML file--->
<cfset toXML = createObject("component", "toXML")>
<!---use the queryToXML function to convert the query results to xml text. dataset will be the name
for the root node and row will be the node that repeats for each row in the query result--->
<cfset peopleXML = toXML.queryToXML(peopleQry, "dataset", "row")>
<!---convert the XML text into an XMLDocument object since we are returning XML--->
<cfset parsedPeopleXML = xmlParse( peopleXML ) >
<!---Set the content returned so that Spry will recognize it as XML. This command is not needed for
Flex 2.0 to use the XML returned, but is needed for Spry. Without this line Spry does not
recognize the returned value as XML.--->
<cfcontent type="application/xml; charset=UTF-8">
<cfreturn parsedPeopleXML />
</cffunction>
I then parse into an XML Document the XML string returned by the toXML CFC's queryToXML function. Now what I will return matches the return type I've specified for this function ( xml ).
Lastly, to ensure that Spry recognizes the returned data as XML I use the cfcontent tag to specify the type as XML. Without this step Spry doesn't properly process the returned data. This step is not necessary for Flex 2.0, but since I want to use the same CFC function for both Spry and Flex user interfaces, I include the tag.
You can view a Flex 2.0 demo that uses the XML returned by the above CFC function here: /flex/cfxml/bin/cfxml.html and a Spry demo here: /flex/cfxml/sprypeople.htm.
I've not done any testing to compare the two methods (use XML as the data provider or use an ArrayCollection containing objects as the data provider) for a List control such as DataGrid.
However, I think the ArrayCollection of Objects would be slower for a large amount of data (thousands of records) since Object creation for thousands of objects could be time consuming. I recall another person blogging about this (try searching MXNA).
However, unless the time difference was a real negative for the user, I think if you need to update the values, add new values, delete values that are being displayed in the data grid, then an ArrayCollection of Objects might be easier to implement.
If you do some testing, post back what you find out.
In the handlResult function I create the xmlResult XML object using the result returned by CF. The datagrid's data provider is bound to xmlResult.row. If you examine the XML returned by CF (see the example app which shows the raw XML), you will see that the root node is named dataset and the node that repeats for each record is called row. So the dataprovider is bound to each row node that is repeated in the XML.
I did a series of tutorials on using XML in Flex (see my Flex blog link to the right), which includes how to set the data provider for a data grid.
http://tech.groups.yahoo.com/group/flexcoders/mess...
The author states that returning 2000 objects from CF to Flex took over 10 seconds vs returning 2000 structures which took only .5 seconds
I'll spare you the entire function and give you the highlight..
<code>
<cfloop query="articles">
<cfset a = articles['#columnName#']>
<cfset articleOutput = articleOutput & a>
</cfloop>
<cfsavecontent variable="articleXML">
<cfoutput>
<?xml version="1.0" encoding="iso-8859-1"?>
<Factiva>
#articleOutput#
</Factiva>
</cfoutput>
</cfsavecontent>
<cfreturn articleXML />
</code>
RECORDSET:
Supervisor | Worker | Job
John , sarah , programmer
John, bill, programmer
Tom, Katie, office assistant
Rather than have the xml returned:
<row >
<SUPERVISOR> John </SUPERVISOR> <WORKER> Sarah </WORKER> <JOB> programmer </JOB>
I would like to receive:
<supervisor name = "john">
<worker name="sarah" job="programmer">
<worker name="bill" job="programmer">
</supervisor>
I imagine this is a basic question but this is my first web/service xml application and I'm kind of at a loss in regards to where to start.
Thanks,
Scott
<supervisor name = "john">
<worker name="sarah" job="programmer">
<worker name="bill" job="programmer">
</supervisor>
would be the better approach as you could easily loop through each supervisor's assigned workers.
<cfcontent type="application/xml; charset=UTF-8">
for spry
This and Ray Camden's tip of putting output="false" as an attribute of cfcomponent got my script running.