Remote Object Auto Update for Flex Applications Search:
home / articles / flex integration  

INTRODUCTION
WebORB 2.1 for .NET introduces a powerful feature enabling application developers to streamline client/server application integration. The feature provides a way to track client-side changes to objects and arrays retrieved via remote method invocations and subsequently update original instance on the server-side with all the changes made to the object by the client application.

This articles consists of the following sections:

FEATURE OVERVIEW

The feature consists of two parts:

  1. A service on the server-side responsible for applying the changes from the client to the original instance of the object and notifying the server-side application about the performed changes.

  2. A client-side SWC component responsible for tracking changes to the objects and sending a summary of changes to the server;

There are two ways to enable auto-update for an object returned from a remote method invocation: (1) object's class can implement the Weborb.Service.IAutoUpdate interface or (2) the method invoked by the client can have the[EnableAutoUpdate()] attribute. Both approaches produce the same result: the returned object is assigned a unique id and placed into session. The id is used later on when client submits updates to the object's data.

The client-side must import the weborb.swc component into the classpath. When result from a remote invocation becomes available, the client application should register it with the WebORB.EnableAutoUpdates() call. At that point, WebORB component tracks any changes made to the object. The client application can submit the changes to the server to update the original instance using the WebORB.Commit() call.

 To demonstrate how the all the parts of the feature come together, consider the example below:
 

AUTO UPDATE EXAMPLE

The example is a rental car service where a car can be rented, its internal state (mileage, wear and tear) changes and then it is returned back. The service managing the cars keeps the same car object for each vehicle. When the client application adds some mileage to the car and adds some wear to the parts, it uses WebORB's auto-update to send the deltas to the server where it applies the changes to the original object.

The Flex application shown above retrieves Car objects. User can change the state of the object by increasing car's mileage or adjusting the wear and tear. When the "Return Vehicle" button is clicked, the client uses WebORB Flex component to send a summary of changes to the server. On the server-side, WebORB applies to the changes to the original instance representing the given Car and puts it back in the pool of available vehicles.

CODE REVIEW - SERVER SIDE

The CarRentalService class is the core of the server-side logic. WebORB exposes the class as a service to Flex application. The class contains a collection of Car objects. Each Car object contains the mileage as well as a collection of CarPart objects. The CarPart objects track wear and tear for the part for a particular car:

Below is the source code for the CarRentalService class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using System;
using Weborb.Service;
using Weborb.Activation;

namespace Examples.Flex.carrental
{
  [SessionActivation()]
  public class CarRentalService
  {
    private Car[] availableCars = {
      new Car( "Ferrari", "Modena 360", 1000 ),
      new Car( "Ford", "Mustang", 1000 ),
      new Car( "VW", "Beetle", 1000 ),
      new Car( "Honda", "Accord", 1000 ),
      new Car( "BMW", "750Li", 1000 ),
      new Car( "Volvo", "XC90", 1000 ),
      new Car( "Mercedes", "S600", 1000 ) };

    [EnableAutoUpdate( typeof( UpdateHandler) )]
    public Car RentACar()
    {
      int carId = new Random().Next( availableCars.Length );
      Car car = availableCars[ carId ];
 
      // we always service our cars before they are rented!
      CarPart engine = (CarPart) car.wearAndTear[ "engine" ];
      if( engine.wearAndTearPercent > 90 )
        engine.wearAndTearPercent = 0;

      CarPart oil = (CarPart) car.wearAndTear[ "oil" ];
      if( oil.wearAndTearPercent == 100 )
        oil.wearAndTearPercent = 0;

      CarPart tires = (CarPart) car.wearAndTear[ "tires" ];
      if( tires.wearAndTearPercent > 90 )
        tires.wearAndTearPercent = 0;

      return car;
    }
  }
}

The class sets up a collection of available cars (lines 10-17). The RentACar() method is invoked by Flex client. Line 19 instructs WebORB to handle the return type as an auto-update object. WebORB assigns a unique id to the Car object returned from the method invocation, so it can apply the changes when they arrive from the client-side. The RentACar() method retrieves a random car from the collection. The method adjusts the wear and tear for car parts if they go above the certain limits (lines 26-36).  The reference to the UpdateHandler type on line 19 specifies the callback type which WebORB will invoke when a car object is updated. The type must implement the Weborb.Service.IUpdateHandler interface. Below is an implementation of the interface used in the example:

public class UpdateHandler : IUpdateHandler
{
  #region IUpdateHandler Members

  public void ObjectChanged( object obj )
  {
    Car car = (Car) obj;
    // the "car" object now has all the updates received from the client
   }

  #endregion
}

It is important to note the significant of the SessionActivation attribute on line 7. The attribute requests WebORB to reuse the same instance of the CarRentalService class for each client session. As a result, each client will deal with its own set of available cars since the availableCars collection (line 10) will be re-created for each client's session.
 

CODE REVIEW - CLIENT SIDE

The auto-update feature requires the WebORB.swc component to be present on the Flex Build Path. Make sure WebORB.swc shows up in the list of imported components as shown in the image below:

The Flex application declares a remote object pointing to the CarRentalService class (see below for configuration mapping "carrentalservice" with the server-side class):
 
<mx:RemoteObject
          id="carrental"
          destination="carrentalservice"
          showBusyCursor="true"
          fault="faultHandler(event)" >
        <mx:method name="RentACar" result="gotCar(event)"/>
</mx:RemoteObject>

When the Flex application loads it invokes the initApp() function which fetches a car from the service:
 
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns="*"
    layout="absolute"
    initialize="initApp()">

<mx:Script>
 <![CDATA[
  // ....
  // ....
  private function initApp():void
  {
    carrental.RentACar();
  }
  // ....
  // ....
</mx:Script>

When the client received a Car object, Flex invokes the gotCar handler:
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private function gotCar( event:ResultEvent ):void
{
  WebORB.EnableAutoUpdates( event );

  car = event.result;
  originalMileage = car.mileage;
  mileage.value = car.mileage;
  mileage.minimum = car.mileage;

  makeModel.text = car.make + " " + car.model;

  oil.value = car.wearAndTear[ "oil" ].wearAndTearPercent;
  originalOilWear = oil.value;

  tires.value = car.wearAndTear[ "tires" ].wearAndTearPercent;
  originalTiresWear = tires.value;

  engine.value = car.wearAndTear[ "engine" ].wearAndTearPercent;
  originalEngineWear = engine.value;

  oilWear.text = String( oil.value ) + "%";
  tiresWear.text = String( tires.value ) + "%";
  engineWear.text = String( engine.value ) + "%";
  mileage.setFocus();
}

The call on line 3 registers the Car object contained inside of the result event with the WebORB component. At that moment any changes made to the Car object (line 5) are tracked and recorded.

The "Return Vehicle" button invokes the "returnTheCar" click handler:
 
1
2
3
4
5
6
7
8
private function returnTheCar() : void
{
  if( !WebORB.HasPendingChanges( car ) )
    Alert.show( "Common, the car has not been driven yet! Put at " +
                "least a mile on it before returning!", "No Changes Detected" );
  else
    WebORB.Commit( car, new CarReturnResponder( this ) );
}

 The API call on line 3 checks if the current car object has any pending changes. If a change is found, line 7 submits the changes to the server. The CarReturnResponder argument is an instance of mx.rpc.IResponder interface. The object gets notified when WebORB finishes updating the server-side object with the changes submitted by the client application.

You can find the full source of the CarRental Flex application at:
 [WEBORB INSTALL DIR\\Examples\Flex\carrental\CarRental.mxml

CONFIGURATION - WEBORB

Flex applications require a declaration of the exposed classes in the form of "destinations". Destinations can be configured in flex-remoting-service.xml located in the WEB-INF\flex folder. The application in this example uses the "carrentalservice" destination defined as:

<destination id="carrentalservice">
  <properties>
    <source>Examples.Flex.carrental.CarRentalService</source>
  </properties>
</destination>

Flex Builder loads the configuration file during the compile time.

In order for WebORB to recognize "carrentalservice" as a reference to a .NET class, WebORB configuration must include a id-to-class declaration. That declaration must be specified in the <services> element of the weborb.config file:

<service>
   <name>carrentalservice</name>
   <serviceId>Examples.Flex.carrental.CarRentalService</serviceId>
</service>

Future WebORB Beta releases will make that service declaration optional and will obtain that information directly from the Flex configuration file.

It is important to note that if a change is made to weborb.config, your corresponding ASP.NET application must be restarted so the change is loaded at the application startup time.
 

RUNNING THE EXAMPLE LOCALLY

If you have not tried to run a Flex application with WebORB for .NET, it is recommended to go through an overview at: http://www.themidnightcoders.com/articles/flextodotnet.htm

WebORB 2.1 distribution contains the code and compiled binaries for the example described in this article. Follow the instructions below to run the example locally:

  1. In Flex Builder 2.0 select File -> New -> Flex Project

  2. In the "New Flex Project" dialog window, select "Flex Data Services" as the project type. Make sure the "Compile application locally in Flex Builder" radio button is selected. Click "Next".

  3. The location of the server root must be the WebORB installation directory. By default WebORB is installed into C:\Inetpub\wwwroot\weborb. The root URL should be http://localhost/weborb. Click "Next".

  4. Enter "Car Rental" for the project name. In the "Project contents" group, deselect the "Use default location" checkbox. Click "Browse" and browse to
        C:\Inetpub\wwwroot\weborb\examples\flex\carrental\client-side
    Click "Next"

  5. Select the "Libraries" tab. Click "Add SWC". Browse to C:\Inetpub\wwwroot\weborb\flex\ and select WebORB.swc. Click "OK". Click "Finish". Flex Builder sets up the CarRental project and opens up CarRental.mxml. The source code of the example is complete, so you can proceed to running it.

  6. Select "Run" from the top menu and "Run" from the submenu. The CarRental application will open in a browser.

 
Copyright © 2003-2006 Midnight Coders, LLC.  Privacy Policy | Contact Webmaster
Home | Products | Customers | Download | Licensing | Forum | Developers | About