Using the Remoting Service, your application can directly invoke methods of Java objects deployed in your application server, and consume the return value. The method can return a value of a primitive data type, an object, a collection of objects, an object graph, and more. Java objects returned by server-side methods are deserialized into either dynamic or typed ActionScript objects.
This section describes how to build a simple inventory management application that demonstrates the BlazeDS Remoting Service.
Note: The turnkey server includes an HSQLDB database, which allows you to run the samples “out-of-the-box” without setting up a database. HSQLDB is a lightweight Java RDBMS that is particularly well-suited to run samples.
To start the sample database:
Execute the following command:
startdb
The server-side of this application uses the simple Data Access Object (DAO) and Value Object patterns:
In the blazeds-server project, right-click the src folder, and select New > Class. Enter “tutorial” as the package name and “Product” as the class name; then click Finish. Implement the Product class as follows:
package tutorial;
public class Product {
private int productId;
private String name;
private double price;
private int qty;
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
package tutorial;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import flex.samples.ConnectionHelper;
import tutorial.Product;
public class ProductDAO {
public List getProducts() throws SQLException {
List list = new ArrayList();
Connection c = null;
try {
c = ConnectionHelper.getConnection();
Statement s = c.createStatement();
ResultSet rs = s.executeQuery("SELECT * FROM product ORDER BY name");
while (rs.next()) {
Product product = new Product();
product.setProductId(rs.getInt("product_id"));
product.setName(rs.getString("name"));
product.setPrice(rs.getDouble("price"));
product.setQty(rs.getInt("qty_in_stock"));
list.add(product);
}
} finally {
c.close();
}
return list;
}
public void update(Product product) throws SQLException {
Connection c = null;
try {
c = ConnectionHelper.getConnection();
PreparedStatement ps = c.prepareStatement(
"UPDATE product SET name=?, price=?, qty_in_stock=? WHERE product_id=?");
ps.setString(1, product.getName());
ps.setDouble(2, product.getPrice());
ps.setInt(3, product.getQty());
ps.setInt(4, product.getProductId());
} finally {
ConnectionHelper.close(c);
}
}
}
A Remoting destination exposes a Java class that your Flex application can invoke remotely. The destination id is a logical name that your Flex application uses to refer to the remote class, which eliminates the need to hardcode a reference to the fully qualified Java class name. This logical name is mapped to the Java class name as part of the destination configuration in remoting-config.xml.
To create a remoting destination for the ProductDAO class:
Add a destination called tutorial-product defined as follows:
<destination id="tutorial-product">
<properties>
<source>tutorial.ProductDAO</source>
</properties>
</destination>Make sure the root folder for LiveCycle Data Services matches the root folder of your BlazeDS web application. The settings should look similar to these (you may need to adjust the exact folder based on your own settings):
Root Folder: C:\blazeds\tomcat\webapps\samples
Root URL: http://localhost:8400/samples/
Context Root: /samples
In the newly created tutorial-product project, open the tutorial-product.mxml file located in the src folder, and implement the application as follows:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:RemoteObject id="ro" destination="tutorial-product"/>
<mx:DataGrid dataProvider="{ro.getProducts.lastResult}" width="100%" height="100%"/>
<mx:Button label="Get Data" click="ro.getProducts()"/>
</mx:Application>RemoteObject calls are asynchronous. You use the result and fault events of the RemoteObject component to handle results and errors. To make the application more robust and better partitioned, modify the code as follows:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.collections.ArrayCollection;
[Bindable]
private var products:ArrayCollection;
private function resultHandler(event:ResultEvent):void
{
products = event.result as ArrayCollection;
}
private function faultHandler(event:FaultEvent):void
{
Alert.show(event.fault.faultString);
}
]]>
</mx:Script>
<mx:RemoteObject id="ro" destination="tutorial-product"
result="resultHandler(event)"
fault="faultHandler(event)"/>
<mx:DataGrid id="dg" dataProvider="{products}" width="100%" height="100%"/>
<mx:Button label="Get Data" click="ro.getProducts()"/>
</mx:Application>
In the application so far, the list of products returned by the getProducts() method is deserialized into dynamic objects. Sometimes, you may want to work with strongly typed objects. To work with typed objects in this application, first create the ActionScript version of the Product class created in step 1:
Implement the Product class as follows:
package
{
[Bindable]
[RemoteClass(alias="tutorial.Product")]
public class Product
{
public var productId:int;
public var name:String;
public var price:Number;
public var qty:int;
}
}Notice that the code uses the [RemoteClass(alias="tutorial.Product")] annotation to map the ActionScript version of the Product class (Product.as) to the Java version (Product.java). As a result, Product objects returned by the getProducts() method of ProductDAO are deserialized into instances of the ActionScript Product class. Similarly, in the next step, the instance of the ActionScript Product class passed as an argument to the update method of the RemoteObject is deserialized into an instance of the Java version of the Product class at the server-side.
Modify the tutorial-product.mxml application as follows to allow the user to update products:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
[Bindable]
private var product:Product;
private function update():void
{
product.name = productName.text;
product.price = Number(price.text);
product.qty = parseInt(qty.text);
ro.update(product);
}
]]>
</mx:Script>
<mx:RemoteObject id="ro" destination="tutorial-product"/>
<mx:DataGrid id="dg" dataProvider="{ro.getProducts.lastResult}" width="100%" height="100%"
change="product = Product(dg.selectedItem)"/>
<mx:Button label="Get Data" click="ro.getProducts()"/>
<mx:Form>
<mx:FormItem label="Name">
<mx:TextInput id="productName" text="{product.name}"/>
</mx:FormItem>
<mx:FormItem label="Price">
<mx:TextInput id="price" text="{product.price}"/>
</mx:FormItem>
<mx:FormItem label="Qty In Stock">
<mx:TextInput id="qty" text="{product.qty}"/>
</mx:FormItem>
<mx:FormItem>
<mx:Button label="Update" click="update()"/>
</mx:FormItem>
</mx:Form>
</mx:Application>