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.

Related Blog Entries

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Hello I've been reading your flex blogs recently and they're really a great help to my job. Keep up the good work. However I've got a question: In your previous post you converted the query to an array of Person objects,and bind this array to a datagrid for displaying the result. Compare with the xml method here,which one will be more efficient (or preferable) if the returned query has a huge amount of records?
# Posted By Richard | 11/13/06 8:25 AM
Thanks for the comment.

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.
# Posted By Bruce | 11/13/06 11:03 AM
Did you use webservice or a RemoteObject to return xml in the example? I am trying to use a RemoteObject to return xml but I don't know how to set the dataProvider in the DataGrid...can you help?
# Posted By Richard | 11/13/06 10:54 PM
In this example I created the XML using ColdFusion and then used RemoteObject in the Flex application to get the XML from ColdFusion. You can right click on the Flex example to see the source code.

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.
# Posted By Bruce | 11/14/06 7:09 AM
Proper MIME type is "text/xml".
# Posted By Andrew Powell | 11/14/06 9:24 PM
Sorry the right click doesn't work....I couldn't see the source code that's why I asked you :p
# Posted By Richard | 11/15/06 12:58 AM
Richard - try again (you may need to refresh the page). I've added the capability to view source (wasn't available initially).
# Posted By Bruce | 11/15/06 10:32 AM
Regarding Richard's question about returning a huge number of of objects vs XML from CF to Flex please see this post on FlexCoders:

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
# Posted By Bruce | 11/21/06 12:31 PM
Thanks for the information :-)
# Posted By Richard | 11/23/06 1:42 AM
Or if you don't want to use Ray Camden's toXML CFC:

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>
# Posted By Clint | 1/25/07 5:44 AM
I can't get the view source to work either. I could really use the source!
# Posted By scott | 2/14/07 2:27 PM
Scott - I'll get the view source working again tonight. I apologize for the problem.
# Posted By Bruce | 2/15/07 2:42 PM
I appreciate you fixing the code. Is there any advice about how I should form my xml? I don't know the best way to form the question so I'll try to give an example.

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
# Posted By scott | 2/16/07 6:48 AM
Scott - sorry that I did not reply to you sooner. I think this:

<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.
# Posted By Bruce | 2/27/07 6:39 AM
New to ColdFudion here. I tried this using the result set of a stored procedure without success. Can you help? Thanks!
# Posted By Tom | 4/14/07 10:23 PM
Tom - I've not tried this using a stored procedure. But if your stored procedure is returning a single result set then it should work. What error are you getting?
# Posted By Bruce | 4/15/07 4:39 AM
If your results are too large, SQL Server will break them up into multiple rows. There is a function on CFLIB.org to handle this.
# Posted By Andrew Powell | 4/15/07 1:30 PM
Thanks for the tip on
<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.
# Posted By Andrew Mercer | 4/28/07 7:47 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1.002. Contact Blog Owner