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.

Additionally, data management helps synchronize your client application with the data on the service. Data management features can automatically update user interface controls that display data retrieved from a service.

This tutorial shows how to use Flash Builder to implement data management. The tutorial illustrates how to synchronize data on the server and with client application controls.

Data management service operations

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.

Note: The required data management operation signatures listed in this tutorial are a subset of the signatures that can be used. For a complete list of the operation signatures you can use, see Enabling data management.

Client-side and server-side typing

This tutorial illustrates both client-side typing and server-side typing. For this tutorial, the client application accesses an Employee object from the data service. The Employee object contains fields, such as name and hire date, that define an employee. With client-side typing, you use Flash Builder wizards to introspect the data on the server and define the Employee data type in client code. With server-side typing, server code defines the Employee data type.

Both PHP and ColdFusion let you define custom data types in server code. Flash Builder recognizes the custom data type during introspection of services. You do not have to walk through the wizard screens to configure the Employee data type.

Whether you use server-side or client-side typing is a developer preference. Server-side typing can help enforce data integrity on the server and simplify the Flash Builder workflow. Client-side typing simplifies the service coding while using Flash Builder to define the custom data types.

Note: Flash Builder can generate sample server code from a database. The sample code generated by Flash Builder illustrates client-side typing. See Generating a sample ColdFusion service from a database table and Generating a sample PHP service from a database table.

Data management tutorial (ColdFusion)

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

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

You can implement the service in this tutorial using client-side or server-side typing. The service is defined in EmployeeService.cfc. If you use server-side typing, you define the Employee data type in a separate Employee.cfc.

The server code in EmployeeService.cfc is basically the same in both versions. However, in the version that implements server-side typing, the functions access the Employee data type defined in Employee.cfc.

Create the remote service and import it into a Flex project (client-side typing)

  1. In your web root create a folder named DataMgtCF.

  2. In your favorite ColdFusion editor, create the following CFC. Name the CFC EmployeeService.cfc and place it in the DataMgtCF folder in your web root.

    EmployeeService.cfc contains the functions required by Flash Builder to implement data management.

    <!--- 
    This sample service contains functions that illustrate typical service operations. 
    This code is for prototyping only. 
    Authenticate the user prior to allowing them to call these methods. You can find more 
    information at http://www.adobe.com/go/cf9_usersecurity 
    ---> 
    <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>
  3. In Flash Builder, create a Flex project. Name the project DataMgtCF. 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 folder for the Output Folder. Click Finish.

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

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

    Provide authorization credentials as needed for your system.

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

    Flash Builder requires 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

    10001

    For getItem(), you supply a valid parameter corresponding to the key field for the database. Number and 10001 are valid type and value for itemID

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

    Flex uses custom data types to access and update complex data types returned from a server. getItem() returns the fields of a record from the Employees table in the database

    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. In the Configure Return Type dialog, Auto-Detect the Return Type is selected by default. Click Next.

  14. Select Use an Existing Data Type. Select Employee from the Array Of drop-down list to specify an array of Employees. Click Finish.

Next:Enable Data Management Features

Create the remote service and import it into a Flex project (server-side typing)

  1. In your web root create a folder named DataMgtCF.

  2. In your favorite ColdFusion editor, create the following CFC. Name the CFC Employee.cfc and place it in the DataMgtCF folder.

    Employee.cfc defines the Employee data type that is returned by the service.

    <cfcomponent> 
        <cfproperty name="emp_id" type="numeric"> 
        <cfproperty name="bdate" type="date"> 
        <cfproperty name="fname" type="string"> 
        <cfproperty name="lname" type="string"> 
        <cfproperty name="gender" type="string"> 
        <cfproperty name="hdate" type="date"> 
    </cfcomponent>
  3. Now create EmployeeService.cfc and place it in the DataMgtCF folder alongside Employee.cfc.

    EmployeeService.cfc contains the functions required by Flash Builder to implement data management.

    <!--- 
    This sample service contains functions that illustrate typical service operations. 
    This code is for prototyping only. 
    Authenticate the user prior to allowing them to call these methods. You can find more 
    information at http://www.adobe.com/go/cf9_usersecurity 
    ---> 
    <cfcomponent output="false"> 
        <cffunction name="getAllEmployees" output="false" access="remote" returntype="Employee[]" > 
            <cfset var returnarray = ArrayNew(1)> 
            <cfset var temp = ""> 
            <cfset var qAllEmployees=""> 
            <cfquery name="qAllEmployees" datasource="fb_tutorial_db"> 
                SELECT * FROM employees 
            </cfquery> 
            <cfloop query="qAllEmployees"> 
                <cfobject component="Employee" name="tempname"> 
                <cfset tempname.emp_id = #qAllEmployees.emp_no#> 
                <cfset tempname.fname = #qAllEmployees.first_name#> 
                <cfset tempname.lname = #qAllEmployees.last_name#> 
                <cfset tempname.gender = #qAllEmployees.gender#> 
                <cfset tempname.bdate = #qAllEmployees.birth_date#> 
                <cfset tempname.hdate = #qAllEmployees.hire_date#> 
                <cfset temp = ArrayAppend(returnarray, tempname)> 
            </cfloop> 
            <cfreturn returnarray> 
        </cffunction>     
        
        <cffunction name="getEmployee" output="false" access="remote"  returntype="Employee" > 
            <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="createEmployee" output="false" access="remote" returntype="numeric" > 
            <cfargument name="item" type="Employee" required="true" /> 
     
                <cfquery name="qCreateEmplyee" 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.fname#">, 
                            <CFQUERYPARAM cfsqltype="CF_SQL_VARCHAR" VALUE="#item.lname#">, 
                            <CFQUERYPARAM cfsqltype="CF_SQL_VARCHAR" VALUE="#item.gender#">, 
                            <CFQUERYPARAM cfsqltype="CF_SQL_DATE" VALUE="#item.bdate#">, 
                            <CFQUERYPARAM cfsqltype="CF_SQL_DATE" VALUE="#item.hdate#">) 
                </cfquery> 
     
            <cfreturn result.GENERATED_KEY/> 
        </cffunction> 
        <cffunction name="updateEmployee" output="false" access="remote" returntype="void" > 
            <cfargument name="item" type="Employee" required="true" /> 
     
            <cfquery name="updateItem" datasource="fb_tutorial_db"> 
                UPDATE employees SET birth_date = <CFQUERYPARAM cfsqltype="CF_SQL_DATE" 
                VALUE="#item.bdate#">, 
                hire_date = <CFQUERYPARAM cfsqltype="CF_SQL_DATE" VALUE="#item.hdate#">, 
                gender = <CFQUERYPARAM cfsqltype="CF_SQL_VARCHAR" VALUE="#item.gender#">, 
                first_name = <CFQUERYPARAM cfsqltype="CF_SQL_VARCHAR" VALUE="#item.fname#">, 
                last_name = <CFQUERYPARAM cfsqltype="CF_SQL_VARCHAR" VALUE="#item.lname#"> 
                WHERE emp_no = <CFQUERYPARAM CFSQLTYPE="CF_SQL_INTEGER" VALUE="#item.emp_id#"> 
            </cfquery> 
        </cffunction> 
     
        <cffunction name="deleteEmployee" 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>
  4. In Flash Builder, create a Flex project. Name the project DataMgtCF. 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

  5. Validate your ColdFusion settings and specify the DataMgtCF folder for the Output Folder. Click Finish.

  6. From the Flash Builder Data menu, select Connect to Data/Service. Select ColdFusion. Click Next.

  7. Click Browse and navigate to the EmployeeService.cfc file you created in step 2. Click Finish.

    Provide authorization credentials as needed for your system.

Next:Enable Data Management Features

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_id and click Next.

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

    • Create (Add) Operation: createEmployee( )

    • Get Item Operation: getEmployee( )

    • Update Operation: updateEmployee( )

    • Delete Operation: deleteEmployee ( )

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

Next:Create the application and add a DataGrid and Buttons

Create the application and add a DataGrid and Buttons

  1. If the MXML editor is in Source mode, 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.

    In the Bind to Data dialog, EmployeeService and getAllEmployees() are selected. Click OK.

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

    Rename and rearrange the columns.

Next:Generate event handlers for the Buttons

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. In Properties view, near the On Click field of the Add button, click the icon. Select Generate Event Handler.

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

  2. In the event handler body, specify the implementation for the event.

    The data types differ slightly for the client-side and server-side implementations. Make sure to use the correct code for the event handler.

    Client-side typing:

    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;

    Server-side typing:

    var e:Employee = new Employee(); 
    var birthDate:Date = new Date(2000, 01, 01); 
    var hireDate:Date = new Date(2000, 01, 01); 
    e.fname = "New"; 
    e.lname = "New"; 
    e.bdate = birthDate; 
    e.hdate = hireDate; 
    e.gender = "M"; 
    dg.dataProvider.addItem(e); 
    dg.verticalScrollPosition = dg.dataProvider.length -1;
  3. In the Script block, add the following import statement after the existing import statements:

    import services.employeeservice.EmployeeService; 
    import valueObjects.Employee;
  4. In Design mode, add an On Click event handler for the Delete button.

    The data types differ slight for the client-side and server-side implementations. Make sure to use the correct code for the event handler.

    Client-side typing:

    employeeService.deleteEmployee(dg.selectedItem.emp_no);

    Server-side typing:

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

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

    employeeService.commit();
  7. For the creationCompleteHandler() for the DataGrid, add the following lines of code:

    protected function dg_creationCompleteHandler(event:FlexEvent):void 
    { 
        employeeService.getDataManager(employeeService.DATA_MANAGER_EMPLOYEE).autoCommit=false; 
        employeeService.getDataManager(employeeService.DATA_MANAGER_EMPLOYEE).deleteItemOnRemoveFromFill=true; 
        getAllItemsResult.token = employeeService.getAllItems(); 
    }

    This code makes sure that deleted items can be reverted by selecting the Revert button.

  8. Save the application and select Run > Run DataMgtCF.

    You can update employees in place in the DataGrid. When you click Save All Changes, the changes are updated on the server. The server is updated is because the data management feature calls the updateItem() operation to keep the data synchronized between the client and the server.

    Click the Revert button to undo any changes you made before you click Save All Changes.

    You can add and delete employees. When you add and delete employees, the data management features take care of adding or removing the DataGrid rows. Without data management enabled, you code the updates to the DataGrid yourself.

    When you add an employee, the Employee Number defaults to zero. This default value 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 Save All Changes button to write all changes to the database.

Data management tutorial (PHP)

The application you create in this tutorial accesses the employee database that you previously downloaded and installed. For information on installing this database, see Installing the Flash Builder tutorial database.

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

You can implement the service in this tutorial using client-side or server-side typing. The service is defined in EmployeeService.php. If you use server-side typing, you define the Employee data type in a separate Employee class defined in EmployeeService.php.

The server code in EmployeeService.php is basically the same in both versions. However, in the version that implements server-side typing, the functions access the Employee data type defined in the Employee class.

Create the remote service and import it into a Flex project (client-side typing)

  1. In your web root, create a folder named DataMgtPHP. Within that folder, create a folder named services.

  2. In your favorite PHP editor, create the following PHP file, which implements a service. Name the file EmployeeService.php and place it in the DataMgtPHP/services folder in your web root.

    <?php 
     
    class EmployeeService { 
     
        var $username = "USERNAME"; 
        var $password = "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 (birth_date, 
                first_name, last_name, gender, hire_date) VALUES (?, ?, ?, ?, ?)"); 
            $this->throwExceptionOnError(); 
     
            mysqli_bind_param($stmt, 'sssss', $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); 
            } 
        } 
    } 
    ?>
  3. Modify the connection variables to provide your server, user name, and password for access to the fb_tutorial_db database.

  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. Specify the DataMgtPHP directory for the Output Folder. Click Finish.

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

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

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

    Flash Builder requires 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

    10001

    For getEmployeesByID(), you supply a valid parameter corresponding to the key field for the database. int and 10001 are valid type and value for itemID.

  11. Specify Employee to define a custom type for returned data.

    Flex uses custom data types to access and update complex data types returned from a server. getEmployeesByID() returns the fields of a record from the Employees table in the database

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

  12. Click Finish to configure Employee as the return type.

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

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

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

  16. Configure the parameter type and return type for deleteEmployees() as follows:

    1. From the context menu for the deleteEmployees() operation, select Configure Input Types. Specify int for the type. Click OK.

    2. From the context menu for the deleteEmployees() operation, select Configure Return Type. Select Use An Existing Type. Specify void. Click Finish.

Next:Enable Data Management Features

Create the remote service and import it into a Flex project (server-side typing)

This release of Flash Builder uses PHP DocBlock comments to recognize server-side data type. The sample service in this example shows how to use DocBlock comments to define a custom data type. The example also shows how to specify a data type for function arguments and return values.

  1. In your web root, create a folder named DataMgtPHP. Within that folder, create a folder named services.

  2. In your favorite PHP editor, create the following PHP file, which implements a service. The service also contains an Employee class that defines the Employee data type.

    Name the file EmployeeService.php and place it in the DataMgtPHP/services folder in your web root.

    <?php 
    class Employee { 
      /** 
       * @var int 
       */ 
      var $emp_id; 
      
      /** 
       * @var string 
       */ 
      var $bdate; 
      
      /** 
       * @var string 
       */ 
      var $fname; 
      
      /** 
       * @var string 
       */ 
      var $lname; 
      
      /** 
       * @var string 
       */ 
      var $gender; 
      
      /** 
       * @var string 
       */ 
      var $hdate; 
    } 
     
    class EmployeeService { 
     
        var $username = "USERNAME"; 
        var $password = "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); 
        } 
         
        /** 
         * Returns all the rows from the table. 
         * 
         * Add authorization or any logical checks 
         * for secure access to your data 
         * 
         * @return Employee[] 
         */ 
        public function getAllEmployees() { 
     
            $stmt = mysqli_prepare($this->connection, "SELECT 
                    employees.emp_no, 
                    employees.birth_date, 
                    employees.first_name, 
                    employees.last_name, 
                    employees.gender, 
                    employees.hire_date 
                 FROM $this->tablename");         
            $this->throwExceptionOnError(); 
             
            mysqli_stmt_execute($stmt); 
            $this->throwExceptionOnError(); 
             
            $rows = array(); 
             
            mysqli_stmt_bind_result($stmt, $row->emp_id, $row->bdate, 
                $row->fname, $row->lname, $row->gender, $row->hdate); 
             
            while (mysqli_stmt_fetch($stmt)) { 
              $rows[] = $row; 
              $row = new stdClass(); 
              mysqli_stmt_bind_result($stmt, $row->emp_id, $row->bdate, 
                    $row->fname, $row->lname, $row->gender, $row->hdate); 
            } 
     
            mysqli_stmt_free_result($stmt); 
            mysqli_close($this->connection); 
     
            return $rows; 
        } 
         
        /** 
         * @param int $itemID 
         * @return Employee 
         */ 
        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, $item->emp_no, $item->bdate, 
                    $item->fname, $item->lname, $item->gender, $item->hdate); 
     
            if(mysqli_stmt_fetch($stmt)) { 
                return $item; 
            } else { 
                return null; 
            } 
        } 
     
       /** 
        * @param Employee $item 
         * @return int 
         */ 
        public function createEmployees($item) { 
     
            $stmt = mysqli_prepare($this->connection, 
                "INSERT INTO $this->tablename (birth_date, 
                first_name, last_name, gender, hire_date) VALUES (?, ?, ?, ?, ?)"); 
            $this->throwExceptionOnError(); 
     
            mysqli_bind_param($stmt, 'sssss', $item->bdate, 
                $item->fname, $item->lname, $item->gender, $item->hdate); 
            $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; 
        } 
     
     
       /** 
        * @param Employee $item 
         */ 
        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_id, $item->bdate, 
                $item->fname, $item->lname, $item->gender, $item->hdate, $item->emp_id); 
            $this->throwExceptionOnError(); 
     
            mysqli_stmt_execute($stmt); 
            $this->throwExceptionOnError(); 
     
            mysqli_stmt_free_result($stmt); 
            mysqli_close($this->connection); 
        } 
     
       /** 
        * @param int $itemID 
         */ 
        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); 
            } 
        } 
    } 
  3. Modify the connection variables to provide your server, user name, and password for access to the fb_tutorial_db database.

  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. Specify the DataMgtPHP directory for the Output Folder. Click Finish.

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

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

Next:Enable Data Management Features

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 Identity Properties dialog, select emp_id. Click Next.

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

    • Create (Add) Operation: createEmployees()

    • Get Item Operation: getEmployeesByID()

    • Update Operation: updateEmployees()

    • Delete Operation: deleteEmployees ()

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

Next:Create the application and add a DataGrid and Buttons

Create the application and add a DataGrid and Buttons

  1. If the MXML editor is in Source mode, 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.

    In the Bind to Data dialog, EmployeeService and getAllEmployees() are selected. Click OK.

  7. (Optional) With the DataGrid selected, in the Properties view click Configure Columns. Rename and rearrange the columns.

Next:Generate and code event handlers for the Buttons

Generate and code event handlers for the Buttons

For each Button, create 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. In Properties view, near the On Click field of the Add button, click the icon. Select Generate Event Handler.

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

  2. In the event handler body, specify the implementation for the event.

    The data types differ slightly for the client-side and server-side implementations. Make sure to use the correct code for the event handler.

    Client-side typing:

    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;

    Server-side typing:

    var e:Employee = new Employee(); 
    e.fname = "New"; 
    e.lname = "New"; 
    e.bdate = "2000-01-01"; 
    e.hdate = "2000-01-01"; 
    e.gender = "M"; 
    dg.dataProvider.addItem(e); 
    dg.verticalScrollPosition = dg.dataProvider.length -1;
  3. In the Script block, add the following import statements after the existing import statements:

    import services.employeeservice.EmployeeService; 
    import valueObjects.Employee;
  4. In Design mode, add an On Click event handler for the Delete button.

    The data types differ slightly for the client-side and server-side implementations. Make sure to use the correct code for the event handler.

    Client-side typing:

    employeeService.deleteEmployees(dg.selectedItem.emp_no);

    Server-side typing:

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

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

    employeeService.commit();
  7. For the creationCompleteHandler() for the DataGrid, add the following lines of code:

    protected function dg_creationCompleteHandler(event:FlexEvent):void 
    { 
        employeeService.getDataManager(employeeService.DATA_MANAGER_EMPLOYEE).autoCommit=false; 
        employeeService.getDataManager(employeeService.DATA_MANAGER_EMPLOYEE).deleteItemOnRemoveFromFill=true; 
        getAllItemsResult.token = employeeService.getAllEmployees(); 
    }

    This code makes sure that deleted items can be reverted by selecting the Revert button.

  8. Save the application and select Run > Run DataMgtPHP.

    You can update employees in place in the DataGrid. When you click Save All Changes, the changes are updated on the server. The server is updated because the data management feature calls the updateEmployees() operation to keep the data synchronized between the client and the server.

    Click the Revert button to undo any changes you made before you click Save All Changes.

    You can add and delete employees. When you add and delete employees, the data management features take care of adding or removing the DataGrid rows. Without data management enabled, you code the updates to the DataGrid yourself.

    When you add an employee, the Employee Number defaults to zero. This default value 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 Save All Changes button to write all changes to the database.