This application demonstrates some important concepts and techniques, which I've outlined in the following sections.
The ColdFusion components correspond very closely to the Java classes used by the Java version of this application (see C:\fds2\jrun4\servers\default\samples\WEB-INF\src\samples\crm):
companyID column, which the application uses to look up the company information when retrieving an employee.CompanyAssembler.cfc is the code that supports managing companies. It uses the CompanyDAO component to perform all of its operations on the company data:
fill returns an array of companies and can take optional parameters to return a specific subset of the data. If not given any arguments, it returns all the companies. If a name is specified, fill returns companies whose name includes that string. If marketSegment is specified, fill returns companies that are in that market segment.get returns a single company and takes a struct as a required argument. This struct contains the properties that you configured in the Flex destination as the identity properties. In this case, the cfcompany destination specifies companyId, so this function can expect a struct with a single key, companyId that contains the company to return.sync takes an array of Flex change objects. These are Java objects that describe the changes a Flex client requests to the database. All create, delete, and update operations call this method, which loops over the array of changes and calls the private methods doCreate, doUpdate, and doDelete based on the type of the change object. This function must return the array of change objects after they have been processed, as this is where the state of each change is kept and passed back to Flex.count takes the same arguments as fill. You can use it for user interface purposes to return the number of records that fill would return with the same arguments. The CRM application does not use count.doCreate creates a new company. The change object contains a Company CFC as the new version of the data, which the application passes to the DAO create function. After processing a change object, the application marks it successfully processed by calling processed() on the change object. If there was an error thrown by the create, the application calls the fail() function on the change object, passing it the details of the failure.doUpdate updates a company. The change object contains both the old and new versions of the company. These are passed along to the DAO, which can use the old data to determine whether any changes to the data were performed since the client last saw an update. If it has, the DAO throws a user-defined exception of type conflict, which the application catches and calls the conflict() function on the change object. Otherwise the application calls processed() or fail() based on the result of the update.doDelete deletes a company. It calls the DAO delete function, passing the entry to be deleted, which is the previous version in the change object. If the delete is successful, the change object is marked as processed. If the DAO is unable to delete the entry because it has changed, it throws a conflict exception; and the application notes the exception in the change object and gives it the current version of the company with that ID.CompanyDAO.cfc is the Data Access Object that performs all the operations for a company in the database:
findCompanies returns a list of companies, and can limit the returned list by matching part of a name or by market segment or both. It creates a CFC for each row returned by the query. It then adds the market segment data using the company_market_segment table, creating an array with an entry for each market segment that a company is in.getCompany returns a single company based on its company ID number.create begins a transaction block and inserts a new record in the table. insertMarketSegments is called to update the company_market_segment table. A select is performed on the newly created company row to retrieve the automatically assigned companyId field. This ID is then set in the passed-in company CFC instance. This is important because Flex needs this information.update begins a transaction block and attempts to update the record in the company table. It uses the original company in the WHERE clause to ensure that the updates are applied only to the version of the data that the client was working with. If the update fails (the number of records affected by the update isn't 1), the application throws a user-defined conflict exception. Otherwise the application updates the market segment of this company if it changed, using the list of changes from the change object.delete removes the company from the database. It removes the company from any employees that have this companyId listed. The application then removes the entries from the market segment table, and then deletes the company record. It uses a WHERE clause to make sure it is deleting a company that matches the data on the client. If the delete fails (the number of records affected by the update isn't 1), the application throws a user-defined conflict exception.count returns the number of records returned if findCompany is called with the same arguments. This function is not used in the CRM example application.insertMarketSegments and deleteMarketSegments insert or remove rows in the company_market_segment table for each segment that the provided company is in.EmployeeAssembler.cfc provides the assembler methods for the cfemployee destination:
fill returns a list of employees. With no arguments, it returns the entire list. The type argument indicates what type of fill to perform. If type is match, the param argument is a string to use to match employee names. If type is byCompany, the param argument is a company ID; fill returns all the employees that work for that company.get returns a single employee with the indicated employeeId. Just like the CompanyAssembler, it takes a required single argument that is a struct. Since the application defines the identity property of this destination to be employeeId, this is the entry that Flex passes in.sync performs the create, update, and delete operations, depending on the provided change objects.count is stubbed out for this assembler; it is not used for the CRM application.doCreate, doUpdate, and doDelete perform the indicated operations in very much the same way the CompanyAssembler does.EmployeeDAO.cfc processes the table of employee data:
read returns the entire list of employees or, if companyId is provided as an argument, it returns the employees that work for that company. Since the employee table has a companyId column and the Employee.cfc contains a company object, the application creates one and sets the companyId in that object.findMatchingEmployees takes a required name parameter and returns a list of employees whose names contain that string.getEmployee takes an employeeId parameter and returns that employee.create creates an employee. Because the employee passed in may or may not have a company associated with it, the application takes special care to extract the companyId from the company if it is there. Otherwise the application sets that column to NULL. It also calls validate() to ensure that the required fields (first name and last name) are set in the provided object.update and delete perform their respective operations in much the same way that the CompanyDAO does.Because the company-to-employee relationship is a one-to-many relationship, it is interesting to look at the Flex destination configuration, which is where you specify the identity fields for the data objects. The cfemployee configuration appears as follows:
<metadata>
<identity property="employeeId"/>
<one-to-many property="company" destination="cfcompany" />
</metadata>
Note the following:
employeeId. This is the name of the property on the ActionScript side of the application. This is also the property in the structure argument of the Get function in your assembler CFC.cfcompany destination as the configuration for managing the company data.Flex Data Services provides a powerful way to manage concurrent access to a data set, including one-to-one and one-to-many relationships. Using the capabilities of ColdFusion to write the back-end logic can save you time and leverage your existing CFML skills while you concentrate on exploring the exciting possibilities of coding applications using Flex 2.
For more information, visit the Flex and ColdFusion topic page in the Flex Developer Center. Continue with Using ColdFusion with Flex – Part 3: Creating and running a phone selector next.