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 operationsData
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 typingThis
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.
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)In 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 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.
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.
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 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)In your web root create a folder named DataMgtCF.
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>
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>
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.
Next:Enable Data Management Features
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_id and
click Next.
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 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 and do the following:
Rename
and rearrange the columns.
Next:Generate event handlers for the Buttons
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, 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;
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.
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);
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();
Add an On click event handler for the Save All Changes button
with the following code:
employeeService.commit();
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.
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)In 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 = "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);
}
}
}
?>
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 2. 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 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.
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 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 getAllEmployees() 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 Types. 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.
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.
In 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. 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);
}
}
}
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 2. Select EmployeeService.php.
Click Finish.
Next:Enable Data Management Features
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_id.
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.
Next:Create the application and add a DataGrid and Buttons
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.
Next:Generate and code event handlers for the Buttons
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, 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;
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.
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);
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();
Add an On click event handler for the Save All Changes button
with the following code:
employeeService.commit();
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.
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.
|
|