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 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.
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 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 projectIn your web root create a folder named DataMgtCF.
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>
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
Validate your ColdFusion settings and specify the DataMgtCF folder
for the Output Folder. Click Finish.
From the Flash Builder Data menu, select Connect to Data/Service.
Select ColdFusion. Click Next.
Click Browse and navigate to the EmployeeService.cfc file
you created in step 2. Click Finish.
Provide authorization
credentials as needed for your system.
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.
In the Configure Return Type dialog, Auto-Detect the Return
Type is selected by default. Click Next.
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
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.
Click Finish to configure the Employee return type.
In the Flash Builder Data/Services view, from the context
menu for the getAllItems() operation, select Configure
Return Type.
Select Use an Existing Data Type. Select Employee[]
from the drop-down list to specify an array of Employees. Click
Finish.
Enable Data Management FeaturesIn the Data/Services view, expand the Data Types
node for EmployeeService and select the Employee data type.
From the context menu for the Employee data type, select
Enable Data Management.
In the Select Unique Identifier dialog, select emp_no and
click Next.
In the Map Database Operations dialog, specify the following
operations. Click Finish.
Create (Add) Operation: createItem( )
Get Item Operation: getItem( )
Update Operation: updateItem( )
Delete Operation: deleteItem ( )
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 ButtonsIf the MXML editor is in Source mode, select Design
to open the MXML editor in Design mode.
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.
In the Properties view, with the DataGrid selected, specify
the following properties:
Property
|
Value
|
ID
|
dg
|
Editable
|
true
|
Drag four Buttons to the Design Area, lining them up beneath
the DataGrid.
Double-click each button to edit their labels. Provide the
following Labels:
Label
|
Add
|
Delete
|
Revert
|
Save All Changes
|
In the Data/Services view, select the getAllItems() operation
and drop it onto the DataGrid.
In the Bind to Data dialog,
EmployeeService and getAllItems() are selected.
Click OK.
(Optional) With the DataGrid selected, in the Properties
view Click Configure Columns and do the following:
Rename
and rearrange the columns.
Generate event handlers for the ButtonsEach 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.
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.
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.
In the Script block, add the following import statement after
the existing import statements:
import services.employeeservice.EmployeeService;
import valueObjects.Employee;
In Design mode, add an On Click event handler for the Delete
button and specify the following code:
employeeService.deleteItem(dg.selectedItem.emp_no);
Similarly, add an On Click event handler for the Revert button
with the following code:
employeeService.getDataManager(employeeService.DATA_MANAGER_EMPLOYEE).revertChanges();
Add an On click event handler for the Save All Changes button
with the following code:
employeeService.commit();
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.
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 projectIn your web root, create a folder named DataMgtPHP.
Within that folder, create a folder named services.
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 = "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);
}
}
}
?>
Modify the connection variables to provide your server, user
name, and password for access to the fb_tutorial_db database.
In Flash Builder, create a Flex project. Name the project
DataMgtPHP and specify PHP for the server technology. Click Next.
Specify the Web Root and Root URL for your system. Validate
your server settings. Specify the DataMgtPHP directory for the Output
Folder. Click Finish.
From the Flash Builder Data menu, select Connect to Data
Service. Select PHP. Click Next.
Click Browse and navigate to the EmployeeService.php file
you created in step 1. Select EmployeeService.php.
Click Finish.
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.
In the Configure Return Type dialog, Auto-Detect the Return
Type is selected by default. Click Next.
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.
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. 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.
Click Finish to configure Employee as the return type.
In the Flash Builder Data/Services view, from the context
menu for the getAllItems() operation, select Configure
Return Type.
In the Configure Return Type dialog, Auto-Detect the Return
Type is selected by default. Click Next.
Select Use an Existing Data Type. Select Employee from
the Array Of drop-down list. Click Finish.
Configure the parameter type and return type for deleteEmployees() as follows:
From the context menu for the deleteEmployees() operation,
select Configure Input Type. Specify int for the type. Click OK.
From the context menu for the deleteEmployees() operation,
select Configure Return Type. Select Use An Existing Type. Specify
void. Click Finish.
Enable Data Management FeaturesIn the Data/Services view, expand the Data Types
node for EmployeeService and select the Employee data type.
From the context menu for the Employee data type, select
Enable Data Management.
In the Select Identity Properties dialog, select emp_no.
Click Next.
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.
Create the application and add a DataGrid and ButtonsIf the MXML editor is in Source mode, select Design
to open the MXML editor in Design mode
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.
In the Properties view, with the DataGrid selected, specify
the following properties:
Property
|
Value
|
ID
|
dg
|
Editable
|
true
|
Drag four Buttons to the Design Area, lining them up beneath
the DataGrid.
Double-click each button to edit their labels. Provide the
following Labels:
Label
|
Add
|
Delete
|
Revert
|
Save All Changes
|
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.
(Optional) With the DataGrid selected, in the Properties
view click Configure Columns. Rename and rearrange the columns.
Generate and code event handlers for the ButtonsFor 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.
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.
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.
In the Script block, add the following import statements
after the existing import statements:
import services.employeeservice.EmployeeService;
import valueObjects.Employee;
In Design mode, add an On Click event handler for the Delete
button and specify the following code:
employeeService.deleteEmployees(dg.selectedItem.emp_no);
Similarly, add an On Click event handler for the Revert button
with the following code:
employeeService.getDataManager(employeeService.DATA_MANAGER_EMPLOYEE).revertChanges();
Add an On click event handler for the Save All Changes button
with the following code:
employeeService.commit();
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.
|