Using data management to synchronize server updates



Data management features allow you to synchronize adding, updating, and deleting of records in a database. Changes you make in the client application are not written to the server until a commit method is called. You can call a revert method to roll back changes made in the client application.

Data management requires a data service that implements one or more operations with the following signatures:

  • createItem(item:CustomDatatype):int

  • deleteItem(itemID:Number):void

  • updateItem((item: CustomDatatype):void

  • getItem(itemID:Number): CustomDatatype

CustomDatatype is a data type representing complex data returned from the server. In server-side typing, the service defines the custom data type. In client-side typing, use Flash Builder to introspect the service and configure the custom data type.

Data Management (ColdFusion)

The application you create in this tutorial accesses the fb_tutorial_db database. For information on installing this database, see Installing the tutorial database

In this tutorial, you create an application that contains an editable DataGrid displaying employee records. You can modify one or more records in place in the DataGrid. You can also add or delete selected records from the DataGrid. All the changes in the DataGrid are local until you select a Save All Changes button that updates the database.

Create the remote service and import it into a Flex project

  1. In your favorite ColdFusion editor, create a ColdFusion service that implements the required data management functions.

    <cfcomponent output="false"> 
        <cffunction name="getAllItems" output="false" access="remote" returntype="any" > 
            <cfset var qAllItems=""> 
            <cfquery name="qAllItems" datasource="fb_tutorial_db"> 
                SELECT * FROM employees 
            </cfquery> 
            <cfreturn qAllItems> 
        </cffunction> 
     
        <cffunction name="getItem" output="false" access="remote"  returntype="any" > 
            <cfargument name="itemID" type="numeric" required="true" /> 
     
            <cfset var qItem=""> 
            <cfquery name="qItem" datasource="fb_tutorial_db"> 
                SELECT * FROM employees 
                    WHERE emp_no = <CFQUERYPARAM CFSQLTYPE="CF_SQL_INTEGER" VALUE="#ARGUMENTS.itemID#"> 
            </cfquery> 
     
             <cfreturn qItem> 
        </cffunction> 
     
        <cffunction name="createItem" output="false" access="remote" returntype="any" > 
            <cfargument name="item" required="true" /> 
     
                <cfquery name="createItem" datasource="fb_tutorial_db" result="result"> 
                    INSERT INTO employees (first_name, last_name, gender, birth_date, hire_date) 
                    VALUES (<CFQUERYPARAM cfsqltype="CF_SQL_VARCHAR" VALUE="#item.first_name#">, 
                            <CFQUERYPARAM cfsqltype="CF_SQL_VARCHAR" VALUE="#item.last_name#">, 
                            <CFQUERYPARAM cfsqltype="CF_SQL_VARCHAR" VALUE="#item.gender#">, 
                            <CFQUERYPARAM cfsqltype="CF_SQL_DATE" VALUE="#item.birth_date#">, 
                            <CFQUERYPARAM cfsqltype="CF_SQL_DATE" VALUE="#item.hire_date#">) 
                </cfquery> 
     
            <cfreturn result.GENERATED_KEY/> 
        </cffunction> 
     
        <cffunction name="updateItem" output="false" access="remote" returntype="void" > 
            <cfargument name="item" required="true" /> 
     
            <cfquery name="updateItem" datasource="fb_tutorial_db"> 
                UPDATE employees SET birth_date = <CFQUERYPARAM cfsqltype="CF_SQL_DATE" 
                VALUE="#item.birth_date#">, 
                hire_date = <CFQUERYPARAM cfsqltype="CF_SQL_DATE" VALUE="#item.hire_date#">, 
                gender = <CFQUERYPARAM cfsqltype="CF_SQL_VARCHAR" VALUE="#item.gender#">, 
                first_name = <CFQUERYPARAM cfsqltype="CF_SQL_VARCHAR" VALUE="#item.first_name#">, 
                last_name = <CFQUERYPARAM cfsqltype="CF_SQL_VARCHAR" VALUE="#item.last_name#"> 
                WHERE emp_no = <CFQUERYPARAM CFSQLTYPE="CF_SQL_INTEGER" VALUE="#item.emp_no#"> 
            </cfquery> 
        </cffunction> 
     
        <cffunction name="deleteItem" output="false" access="remote" returntype="void" > 
            <cfargument name="itemID" type="numeric" required="true" /> 
     
            <cfquery name="delete" datasource="fb_tutorial_db"> 
                    DELETE FROM employees 
                    WHERE emp_no = <CFQUERYPARAM CFSQLTYPE="CF_SQL_INTEGER" VALUE="#ARGUMENTS.itemID#"> 
            </cfquery>     
        </cffunction> 
     
    </cfcomponent>
  2. Save the service in the web root of your ColdFusion installation.

    Name the file EmployeeService.cfc and place it in a directory named DataMgtCF.

  3. In Flash Builder, create a Flex project. Name the project DataMgtCF and specify ColdFusion for the server technology as listed below. Click Next.

    • Application Server Type: ColdFusion

    • Enable Use Remote Object Access Service

    • Select ColdFusion Flash Remoting

  4. Validate your ColdFusion settings and specify the DataMgtCF directory for the Output Folder. Click Finish.

  5. From the Flash Builder Data menu, select Connect to Data Service. Select ColdFusion and click Next.

  6. Click Browse and navigate to the EmployeeService.cfc file you created in step 1. Click Finish.

  7. In the Flash Builder Data/Services view, from the context menu for the getItem() operation, select Configure Return Type.

    Flash Builder needs to configure a custom data type for data returned from the data service. By introspecting the getItem() operation, you can define the custom data type Employee.

  8. In the Configure Return Type dialog, Auto-Detect the Return Type is selected by default. Click Next.

  9. Specify a value and type for the parameter to the getItem() operation as described below. Click Next:

    Argument

    Argument Type

    Value

    itemID

    Number

    10002

    You need to supply valid parameters to the operation for Flash Builder to introspect the operation. 10002 is a valid itemID.

  10. Specify Employee in the Array Of field toto define a custom type for returned data.

    Flex uses custom data types to access and update complex data types returned from a server.

    The Configure Return Type dialog displays the properties of the data type returned by the service.

  11. Click Finish to configure the Employee return type.

  12. In the Flash Builder Data/Services view, from the context menu for the getAllItems() operation, select Configure Return Type.

  13. Select Use an Existing Data Type. Select Employee from the Array Of drop-down list. Click Finish.

Enable Data Management Features

  1. In the Data/Services view, expand the Data Types node for EmployeeService and select the Employee data type.

  2. From the context menu for the Employee data type, select Enable Data Management.

  3. In the Select Unique Identifier dialog, select emp_no and click Next.

  4. In the Map Database Operations dialog, specify the following operations. Click Finish.

    • Create (Add) Operation: createItem( item: Employee )

    • Get Item Operation: getItem( itemID: Number )

    • Update Operation: updateItem( item: Employee )

    • Delete Operation: deleteItem ( itemID: Number )

    Data management is now enabled for this operation. Flash Builder generates client code that can update data using a combination of the mapped operations.

Create the application and add a DataGrid and Buttons

  1. Select Design to open the MXML editor in Design mode.

  2. From the Components view, drag a DataGrid component onto the Design Area and place it near the top.

    The DataGrid component is available under Data Controls.

  3. In the Properties view, with the DataGrid selected, specify the following properties:

    Property

    Value

    ID

    dg

    Editable

    true

  4. Drag four Buttons to the Design Area, lining them up beneath the DataGrid.

  5. Double-click each button to edit their labels. Provide the following Labels:

    Label

    Add

    Delete

    Revert

    Save All Changes

  6. In the Data/Services view, select the getAllItems() operation and drop it onto the DataGrid.

  7. With the DataGrid selected, in the Properties view Click Configure Columns and do the following:

    • Select emp_no column. In the Data Binding area, deselect the editable check box.

      emp_no is a key field that is automatically generated by the database.

    • (Optional) Rename and rearrange the columns.

Generate event handlers for the Buttons

Each Button requires an event handler to specify the action to take when the Button is clicked. Flash Builder generates stubs for event handlers, which you can then code to specify the service actions to take.

  1. Select the Add button. Then, for the On Click field of the Add button, click the Pencil icon and then select Generate Event Handler.

    The MXML editor changes to Source View, placing the cursor in the generated event handler.

  2. In the Script block, add the following import statement:

    import services.employeeservice.EmployeeService; 
    import valueObjects.Employee;
  3. In the event handler body, type the following:

    var e:Employee = new Employee(); 
    var birthDate:Date = new Date(2000, 01, 01); 
    var hireDate:Date = new Date(2000, 01, 01); 
     
    e.first_name = "New"; 
    e.last_name = "New"; 
    e.birth_date = birthDate; 
    e.hire_date = hireDate; 
    e.gender = "M"; 
    dg.dataProvider.addItem(e); 
    dg.verticalScrollPosition = dg.dataProvider.length -1;

    As you type, Flash Builder content assist helps you view the available methods and values.

  4. Modify the DataGrid columns for birth_date and hire_date to add a date chooser:

    <mx:DataGridColumn headerText="birth_date" editorDataField="selectedDate" 
        dataField="birth_date" itemEditor="mx.controls.DateField"/> 
     
    <mx:DataGridColumn headerText="hire_date" editorDataField="selectedDate" 
        dataField="hire_date" itemEditor="mx.controls.DateField"/> 
  5. In Design mode, add an On Click event handler for the Delete button and specify the following code:

    employeeService.deleteItem(dg.selectedItem.emp_no);
  6. Similarly, add an On Click event handler for the Revert button with the following code:

    employeeService.getDataManager(employeeService.DATA_MANAGER_EMPLOYEE).revertChanges();
  7. Add an On click event handler for the Save All Changes button with the following code:

    employeeService.commit();
  8. Save the application and select Run > Run DataMgtCF.

    You can update and delete selected employees in the DataGrid. You can also add new employees.

    When you add an employee, the Employee Number defaults to zero. This is because the new employee has not been updated on the server. When you click Save All Changes, the new employee is added to the server. At that time, an Employee Number is generated.

    Click the Revert button to undo any changes you made.

    Click the Save All Changes button to write all changes to the database.

Data Management (PHP)

The application you create in this tutorial accesses the employee database that you previously downloaded and installed.

In this tutorial, you create an application that contains an editable DataGrid displaying employee records. You can modify one or more records in place in the DataGrid, and also add or delete selected records from the DataGrid. All the changes in the DataGrid are local until you select a Save All Changes button, which updates the database.

Create the remote service and import it into a Flex project

  1. In your favorite PHP editor, create a PHP service class that implements the required data management functions.

    <?php 
     
    class EmployeeService { 
     
        var $username = "root"; 
        var $password = ""; 
        var $server = "localhost"; 
        var $port = "3306"; 
        var $databasename = "fb_tutorial_db"; 
        var $tablename = "employees"; 
     
        var $connection; 
     
        public function __construct() { 
            $this->connection = mysqli_connect( 
                                      $this->server, 
                                      $this->username, 
                                      $this->password, 
                                      $this->databasename, 
                                      $this->port 
                                  ); 
     
            $this->throwExceptionOnError($this->connection); 
        } 
     
        public function getAllEmployees() { 
     
            $stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename");         
            $this->throwExceptionOnError(); 
             
            mysqli_stmt_execute($stmt); 
            $this->throwExceptionOnError(); 
             
            $rows = array(); 
             
            mysqli_stmt_bind_result($stmt, $row->emp_no, $row->birth_date, 
                    $row->first_name, $row->last_name, $row->gender, $row->hire_date); 
     
            while (mysqli_stmt_fetch($stmt)) { 
              $rows[] = $row; 
              $row = new stdClass(); 
              mysqli_stmt_bind_result($stmt, $row->emp_no, $row->birth_date, 
                    $row->first_name, $row->last_name, $row->gender, $row->hire_date); 
            } 
     
            mysqli_stmt_free_result($stmt); 
            mysqli_close($this->connection); 
     
            return $rows; 
        } 
     
        public function getEmployeesByID($itemID) { 
     
            $stmt = mysqli_prepare($this->connection, 
                                    "SELECT * FROM $this->tablename where emp_no=?"); 
            $this->throwExceptionOnError(); 
     
            mysqli_bind_param($stmt, 'i', $itemID); 
            $this->throwExceptionOnError(); 
     
            mysqli_stmt_execute($stmt); 
            $this->throwExceptionOnError(); 
     
            mysqli_stmt_bind_result($stmt, $row->emp_no, $row->birth_date, 
                    $row->first_name, $row->last_name, $row->gender, $row->hire_date); 
     
            if(mysqli_stmt_fetch($stmt)) { 
                return $row; 
            } else { 
                return null; 
            } 
        } 
     
        public function createEmployees($item) { 
     
            $stmt = mysqli_prepare($this->connection, 
                "INSERT INTO $this->tablename (emp_no, birth_date, 
                first_name, last_name, gender, hire_date) VALUES (?, ?, ?, ?, ?, ?)"); 
            $this->throwExceptionOnError(); 
     
            mysqli_bind_param($stmt, 'isssss', $item->emp_no, $item->birth_date, 
                $item->first_name, $item->last_name, $item->gender, $item->hire_date); 
            $this->throwExceptionOnError(); 
     
            mysqli_stmt_execute($stmt); 
            $this->throwExceptionOnError(); 
     
            $autoid = mysqli_stmt_insert_id($stmt); 
     
            mysqli_stmt_free_result($stmt); 
            mysqli_close($this->connection); 
     
            return $autoid; 
        } 
     
        public function updateEmployees($item) { 
     
            $stmt = mysqli_prepare($this->connection, 
            "UPDATE $this->tablename SET emp_no=?, birth_date=?, 
                first_name=?, last_name=?, gender=?, hire_date=? 
                WHERE emp_no=?"); 
            $this->throwExceptionOnError(); 
     
            mysqli_bind_param($stmt, 'isssssi', $item->emp_no, $item->birth_date, 
                $item->first_name, $item->last_name, $item->gender, $item->hire_date, $item->emp_no); 
            $this->throwExceptionOnError(); 
     
            mysqli_stmt_execute($stmt); 
            $this->throwExceptionOnError(); 
     
            mysqli_stmt_free_result($stmt); 
            mysqli_close($this->connection); 
        } 
     
        public function deleteEmployees($itemID) { 
     
            $stmt = mysqli_prepare($this->connection, 
                "DELETE FROM $this->tablename WHERE emp_no = ?"); 
            $this->throwExceptionOnError(); 
     
            mysqli_bind_param($stmt, 'i', $itemID); 
            mysqli_stmt_execute($stmt); 
            $this->throwExceptionOnError(); 
     
            mysqli_stmt_free_result($stmt); 
            mysqli_close($this->connection); 
        } 
     
        /** 
         * Utitity function to throw an exception if an error occurs 
         * while running a mysql command. 
         */ 
        private function throwExceptionOnError($link = null) { 
            if($link == null) { 
                $link = $this->connection; 
            } 
            if(mysqli_error($link)) { 
                $msg = mysqli_errno($link) . ": " . mysqli_error($link); 
                throw new Exception('MySQL Error - '. $msg); 
            } 
        } 
    } 
    ?>
  2. Modify the connection variables to provide your server, username, and password for access to the fb_tutorial_db database.

  3. Save the service in the web root of your PHP installation, as described below.

    • In your web root directory, create a directory named DataMgtPHP.

    • In the DataMgtPHP directory, create a directory named services.

    • Name the file EmployeeService.php and save it in the services directory.

  4. In Flash Builder, create a Flex project. Name the project DataMgtPHP and specify PHP for the server technology. Click Next.

  5. Specify the Web Root and Root URL for your system. Validate your server settings and specify the DataMgtPHP directory for the Output Folder. Click Finish.

  6. From the Flash Builder Data menu, select Connect to Data Service. Select PHP and click Next.

  7. Click Browse and navigate to the EmployeeService.php file you created in step 1. Select EmployeeService.php and click Finish.

  8. In the Flash Builder Data/Services view, from the context menu for the getEmployeesbyID() operation, select Configure Return Type.

    Flash Builder needs to configure a custom data type for data returned from the data service. By introspecting the getEmployeesbyID() operation, you can define the custom data type Employee.

  9. In the Configure Return Type dialog, Auto-Detect the Return Type is selected by default. Click Next.

  10. Specify a value and type for the parameter to the getEmployeesbyID() operation as described below. Click Next:

    Argument

    Argument Type

    Value

    itemID

    int

    10002

    You need to supply valid parameters to the operation for Flash Builder to introspect the operation. 10002 is a valid itemID.

  11. Specify Employee in the Array Of field toto define a custom type for returned data.

    Flex uses custom data types to access and update complex data types returned from a server.

    The Configure Return Type dialog displays the properties of the data type returned by the service.

  12. Click Finish to configure the Employee return type.

  13. In the Flash Builder Data/Services view, from the context menu for the getAllItems() operation, select Configure Return Type.

  14. Configure the return type for the deleteEmployees(), specifying the parameter and type as described below. Click Next and Finish.

    Argument

    Argument Type

    Value

    itemID

    int

    10001

  15. Select Use an Existing Data Type. Select Employee from the Array Of drop-down list. Click Finish.

Enable Data Management Features

  1. In the Data/Services view, expand the Data Types node for EmployeeService and select the Employee data type.

  2. From the context menu for the Employee data type, select Enable Data Management.

  3. In the Select Unique Identifier dialog, select emp_no and click Next.

  4. In the Map Database Operations dialog, specify the following operations and click Finish.

    • Create (Add) Operation: createEmployees( item: Employee )

    • Get Item Operation: getEmployeesByID( itemID: Number )

    • Update Operation: updateEmployees( item: Employee )

    • Delete Operation: deleteEmployees ( itemID: Number )

    Data management is now enabled for this operation. Flash Builder generates client code that can update data using a combination of the mapped operations.

Create the application and add a DataGrid and Buttons

  1. Select Design to open the MXML editor in Design mode.

  2. From the Components view, drag a DataGrid component onto the Design Area and place it near the top.

    The DataGrid component is available under Data Controls.

  3. In the Properties view, with the DataGrid selected, specify the following properties:

    Property

    Value

    ID

    dg

    Editable

    true

  4. Drag four Buttons to the Design Area, lining them up beneath the DataGrid.

  5. Double-click each button to edit their labels. Provide the following Labels:

    Label

    Add

    Delete

    Revert

    Save All Changes

  6. In the Data/Services view, select the getAllEmployees() operation and drop it onto the DataGrid.

  7. With the DataGrid selected, in the Properties view Click Configure Columns and do the following:

    • Select emp_no column. In the Data Binding area, deselect the editable check box.

      emp_no is a key field that is automatically generated by the database.

    • (Optional) Rename and rearrange the columns.

  8. (Optional) Click Configure Columns to rename and rearrange the columns.

Generate and code event handlers for the Buttons

Each Button needs an event handler to specify the action to take when the Button is clicked. Flash Builder generates stubs for event handlers, which you can then code to specify the service actions to take.

  1. Select the Add button. Then, for the On Click field of the Add button, click the Pencil icon and then select Generate Event Handler.

    The MXML editor changes to Source View, placing the cursor in the generated event handler.

  2. In the Script block, add the following import statement:

    import services.employeeservice.EmployeeService; 
    import valueObjects.Employee;
  3. In the event handler body, type the following:

    var e:Employee = new Employee(); 
    e.first_name = "New"; 
    e.last_name = "New"; 
    e.birth_date = "2000-01-01"; 
    e.hire_date = "2000-01-01"; 
    e.gender = "M"; 
    dg.dataProvider.addItem(e); 
    dg.verticalScrollPosition = dg.dataProvider.length -1;

    As you type, Flash Builder content assist helps you view the available methods and values.

  4. In Design mode, add an On Click event handler for the Delete button and specify the following code:

    employeeService.deleteEmployees(dg.selectedItem.emp_no);
  5. Similarly, add an On Click event handler for the Revert button with the following code:

    employeeService.getDataManager(employeeService.DATA_MANAGER_EMPLOYEE).revertChanges();
  6. Add an On click event handler for the Save All Changes button with the following code:

    employeeService.commit();
  7. Save the application and select Run > Run DataMgtPHP.

    You can update and delete selected employees in the DataGrid. You can also add new employees.

    When you add an employee, the Employee Number defaults to zero. This is because the new employee has not been updated on the server. When you click Save All Changes, the new employee is added to the server. At that time, an Employee Number is generated.

    Click the Revert button to undo any changes you made.

    Click the Save All Changes button to write all changes to the database.