ColdFusion 9.0 Resources |
Writing the ColdFusion CFCsWhen you create your ColdFusion CFCs, you can do one of the following:
You place the database manipulation functionality directly in the methods in the assembler CFC and create a Value Object CFC, which is a CFC that contains property definitions and related get and set methods. To separate the lower level database functionality from the high-level Flex assembler operations, you create a Data Access Object (DAO) CFC that contains the lower level database functionality. Using this approach, which is the Bean/DAO methodology, requires that you place the fill, get, sync, and count methods in the assembler CFC. The methods in the assembler CFC call methods in the DAO CFC that perform the lower level database functions such as retrieving records. The DAO CFC creates Value Objects, which are CFCs that contain the values. A Value Object is essentially a row in the result set. The LiveCycle Data Management Service recognizes the methods: fill, get, sync, and count. The fill method retrieves records from a database and populates an array with the records. The get method retrieves a specific record. The sync method lets you keep track of synchronization conflicts by accepting a change list, which is an array of change objects. The count method returns a number that indicates how many records are in a result set. To perform any of these database tasks, the Flex application calls the appropriate fill, get, sync, or count method in the assembler CFC. You can also use a fillContains method, which checks whether to update the results of a fill. For more information, see Managing fills. Creating the fill methodThe fill method retrieves records from a database and populates an array with the records. If you use the Bean/DAO methodology, you create the lower level read method separately in the DAO CFC. The fill method returns the results of a read operation. In the fill method, you create an array to hold the results of the read, and then return the results of the read operation. The essential elements of a fill method appear as follows: <cffunction name="fill" output="no" returntype="samples.contact.Contact[]" access="remote"> <cfreturn variables.dao.read()> </cffunction> You can return a Value Object CFC, a query, or an array of CFML structures. Using a query instead of a Value Object CFC may improve performance. However, ColdFusion cannot handle nested results sets when you use a query. For example, if one of the CFC properties you are returning from the fill method was populated with another complex type such as another CFC type, ColdFusion cannot automatically convert a column in the query to an object with a custom type. In this case, you return an array of CFCs, and the fill method or the read method in the DAO CFC constructs the correct object. You can use structures wherever you currently create a ColdFusion component in the Assembler. However, you still receive CFC Value Objects from Flex. For example, the Change Objects that you receive in the sync method contain CFCs, assuming that you have a remote alias defined in the ActionScript type. You can create Value Object CFCs in the get method. However, using the structure functionality, you can create and return a structure instead of a CFC, because the structures are translated in the same way as CFCs. You can also return an array of structures from the fill method instead of an array of CFCs, for example, if you have to do processing on your data and working with CFCs isn't fast enough. Generally, structures are faster than CFCs. You also use structures when a member of the result object is a complex object. In this case, you create another structure as the value of that key and provide the __type__ key for it. You specify the returntype of the fill method as a Value Object CFC, a query, or an array:
In addition to specifying the returntype of the fill function depending on whether you are using Value Objects, a query, or an array of structures, you also do the following in the lower level read function:
Managing fillsTo determine whether to refresh a fill result after an item is created or updated, you include a fillContains method in the assembler and set both use-fill-contains and auto-refresh to true in the fill-method section of the data-management-config.xml file. The following example shows a fill-method section: <fill-method> <use-fill-contains>true</use-fill-contains> <auto-refresh>true</auto-refresh> <ordered>false</ordered> </fill-method> In this example, ordered is set to false because the fill result is not sorted by any criteria. However, if the fill result is sorted, you set ordered to true. When an item changes in a fill result that is ordered, refresh the entire fill result. The fillContains method tells the Flex application whether it is necessary to run the fill again after an item in the fill result has changed. The fillCcontains method returns a value that indicates how the fill be treated for that change. When the fillContains method returns true, the fill is executed after a create or update operation. The following example shows the fillContains method signature: <cffunction name="fillContains" output="no" returnType="boolean" access="remote"> <cfargument name="fillArgs" type="array" required="yes"> <cfargument name="item" type="[CFC type object]" required="yes"> <cfargument name="isCreate" type="boolean" required="yes"> The fillContains method has the following arguments:
A sample fillContains method, which determines whether the fill arguments (part of the first or last name) are in the Contact item passed to the function, is as follows: <cffunction name="fillContains" output="no" returnType="boolean"access="remote"> <cfargument name="fillArgs" type="array" required="yes"> <cfargument name="item" type="samples.contact.Contact" required="yes"> <cfargument name="isCreate" type="boolean" required="yes"> <cfif ArrayLen(fillArgs) EQ 0> <!--- This is the everything fill. ---> <cfreturn true> <cfelseif ArrayLen(fillArgs) EQ 1> <!--- This is a search fill. ---> <cfset search = fillArgs[1]> <cfset first = item.getFirstName()> <cfset last = item.getLastName()> <!--- If the first or last name contains the search string, ---> <cfif (FindNoCase(search, first) NEQ 0) OR (FindNoCase(search, last) NEQ 0)> <!--- this record is in the fill. ---> <cfreturn true> <cfelse> <!--- this record is NOT in the fill. ---> <cfreturn false> </cfif> </cfif> <!--- By default, do the fill.---> <cfreturn true> </cffunction> If you are running LiveCycle Data Services ES locally, you can determine whether a fill operation is a refresh or a client triggered fill. You do so by calling the DataServiceTransaction.getCurrentDataServiceTransaction().isRefill() method in your ColdFusion application as follows: <cfscript> dst = CreateObject("java", "flex.data.DataServiceTransaction"); t = dst.getCurrentDataServiceTransaction(); isRefill = t.isRefill(); </cfscript> This does not work over RMI when ColdFusion and Flex are not in the same web application. Creating the get methodThe get method retrieves a specific record. The get method calls the lower level read method. If you use the Bean/DAO methodology, as described in Writing the ColdFusion CFCs, you create the lower level read method separately in the DAO CFC. The following example shows the essential elements of a get method: <cffunction name="get" output="no" returnType="samples.contact.Contact" access="remote"> <cfargument name="uid" type="struct" required="yes"> <cfset key = uid.contactId> <cfset ret=variables.dao.read(id=key)> <cfreturn ret[1]> </cffunction> The returntype of a get method can be any of the following:
Creating the sync methodThe sync method lets you keep track of synchronization conflicts by accepting a change list, which is an array of change objects. In the sync method, you pass in an array of changes, loop over the array and apply the changes, and then return the change objects, as follows: <cffunction name="sync" output="no" returnType="array" access="remote"> <cfargument name="changes" type="array" required="yes"> <!-- Create the array for the returned changes. --> <cfset var newchanges=ArrayNew(1)> <!-- Loop over the changes and apply them. ---> <cfloop from="1" to="#ArrayLen(changes)#" index="i" > <cfset co = changes[i]> <cfif co.isCreate()> <cfset x = doCreate(co)> <cfelseif co.isUpdate()> <cfset x = doUpdate(co)> <cfelseif co.isDelete()> <cfset x = doDelete(co)> </cfif> <cfset ArrayAppend(newchanges, x)> </cfloop> <!-- Return the change objects, which indicate success or failure. ---> <cfreturn newchanges> </cffunction> Creating the count methodThe count method returns a number that indicates how many records are in a result set. If you use the Bean/DAO methodology, as described in Writing the ColdFusion CFCs, you create the lower level count method separately in the DAO CFC. The count method contains the following essential elements, without any error handling: <cffunction name="count" output="no" returntype="Numeric" access="remote"> <cfargument name="param" type="string" required="no"> <cfreturn variables.dao.count()> </cffunction> This count method calls a different count method in the DAO CFC, which contains the following essential elements, without any error handling: <cffunction name="count" output="false" access="public" returntype="Numeric"> <cfargument name="id" required="false"> <cfargument name="param" required="false"> <cfset var qRead=""> <cfquery name="qRead" datasource="FDSCFCONTACT"> select COUNT(*) as totalRecords from Contact </cfquery> <cfreturn qRead.totalRecords> </cffunction> |