3 August 2009
This tutorial is written for:
All
Welcome to Part 8 of this tutorial series. In this part, you will transform the Flex application that you built in Parts 1 through 6 into a Rich Island and integrate it into the Web Dynpro application from Part 7. If you did not step through those tutorials, you can download the finished Flex Builder project archive and the SAP nugget archive from the Requirements section below.
First you will add the Rich Islands library to the Flex Builder project. This ActionScript library is needed for the data translation between Flex and SAP. Then you will create setter and getter functions to create properties and handle the asynchronous data from SAP.
In this section you will download the Rich Islands ActionScript library and add it to the Flex Builder project. This allows the application to access the Rich Islands features that handle the data translation between Flex and SAP.
View the following video to better understand how SAP has implemented the Rich Islands functionality:
Video:
The WDIslandLibrary.swc is strictly for Flex 2.0.1. If you plan to use Flex 3.0, you will need to use the WDIslandLibrary30.swc which, at the time of this writing, has not been released by SAP. See the following video to understand how these different versions of the SWC coordinate with the NetWeaver 7.01 ABAP trial version:
Video:
In this section, you will transform this wagon assembly line Flex application into a Rich Island for SAP. This will require importing the FlashIsland class to access Rich Island functionality, creating additional getter and setter functions to detect the asynchronous data changes between Flex and the Web Dynpro application, and making general syntax changes.
import sap.FlashIsland;
This gives the application access to the methods that are necessary to interact with SAP.
init that takes no arguments and returns a void data type. register() method of the FlashIsland package and pass this as an argument. The this keyword is an object self-reference, and in this case registers this Flex application as a Rich Island using the register() method of the FlashIsland class.
private function init():void
{
FlashIsland.register(this);
}
Application tag and change the initialize property value to init().<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
. . .
initialize="init()"
xmlns:comp="components.*">
This registers the entire Flex application with the Rich Islands framework when the application initializes. Now it can be used as a UI element in the Web Dynpro component.
In Part 7 you created the Web Dynpro component with a table UI element. You are removing the Flex framework DataGrid control so that it can be functionally replaced by the table UI element to display the inventory data.
In this section, you will create setter and getter functions for ActionScript properties that will be passed from the Web Dynpro application. The data from the Web Dynpro application is set asynchronously, which means that the Flex Rich Island cannot expect the data to arrive at a consistent time. A setter function will run when the data arrives, which allows you to predictably run code only when the data is present.
populateData() function and delete it.The populateData() function creates the dummy data for the Flex application. You are deleting it because you will replace it with data from the Web Dynpro application.
startProduction() function and delete the populateData() function call.set keyword, create a public function named wagonInventory that takes one argument named _wagonInventory with a data type of the ArrayCollection class and has a return type of void.Note: Remember that it is common convention to name the private class variable, which is associated with the public variable, using a leading underscore (_) character. In an earlier tutorial, you created the private _wagonInventory property. The wagon inventory data that populates the table UI element in the Web Dynpro context is also passed to the equivalent public variable in Flex. You created that context in Part 7. You are now setting the public variable to the private variable.
public function set wagonInventory(_wagonInventory:ArrayCollection):void
{
}
_wagonInventory to this.wagonInventory. Note: Remember that the this keyword is a self reference. In this case, this._wagonInventory refers to the _wagonInventory private variable for this application. The _wagonInventory reference in the value statement refers to the one attribute of data defined in the set function and passed from the Web Dynpro application to the rich island.
public function set wagonInventory(_wagonInventory:ArrayCollection):void
{
this._wagonInventory = _wagonInventory;
}
get keyword, create a public function named wagonInventory that takes no arguments and returns an ArrayCollection class data type.return keyword, return the _wagonInventory variable.public function get wagonInventory():ArrayCollection
{
return _wagonInventory;
}
_wagonYellowWarningAmountThe rest of the getter and setter functions you will create now will accept equivalent Web Dynpro attributes that you created in Tutorial 7 in the component controller context.
[Bindable]
private var _wagonYellowWarningAmount:uint;
set keyword, create a public function named wagonYellowWarningAmount that takes one argument named _wagonYellowWarningAmount with a data type of the uint class. The function returns a void data type._wagonYellowWarningAmount to this._wagonYellowWarningAmount.public function set wagonYellowWarningAmount(_wagonYellowWarningAmount:uint):void
{
this._wagonYellowWarningAmount = _wagonYellowWarningAmount;
}
get keyword, create a public function named wagonYellowWarningAmount that takes no arguments and returns a uint data type.return keyword, return the _wagonYellowWarningAmount variable.public function get wagonYellowWarningAmount():uint
{
return _wagonYellowWarningAmount;
}
_wagonRedWarningAmount variable and remove the value assignment.[Bindable]
private var _wagonRedWarningAmount:uint;
set keyword, create a public function named wagonRedWarningAmount that takes one argument named _wagonRedWarningAmount and data type it to the uint class. The function returns a void data type._wagonRedWarningAmount to this._wagonRedWarningAmount.public function set wagonRedWarningAmount(_wagonRedWarningAmount:uint):void
{
this._wagonRedWarningAmount = _wagonRedWarningAmount;
}
get keyword, create a public function named wagonRedWarningAmount that takes no arguments and returns a uint data type.return keyword, return the _wagonRedWarningAmount variable.public function get wagonRedWarningAmount():uint
{
return _wagonRedWarningAmount;
}
_wagonProductionRate variable and remove the value assignment.[Bindable]
private var _wagonProductionRate:uint;
set keyword, create a public function named wagonProductionRate that takes one argument named _wagonProductionRate and data type it to the uint class. The function returns a void data type._wagonProductionRate to this._wagonProductionRate.public function set wagonProductionRate(_wagonProductionRate:uint):void
{
this._wagonProductionRate = _wagonProductionRate;
}
get keyword, create a public function named wagonProductionRate that takes no arguments and returns a uint data type.return keyword, return the _wagonProductionRate variable.public function get wagonProductionRate():uint
{
return _wagonProductionRate;
}
The private _wagonInventory, _wagonRedWarningAmount, _wagonYellowWarningAmount, and _wagonProductionRate variables are populated through the associated ActionScript public setter functions with data from the Web Dynpro application. Since Flex executes asynchronously, your Rich Island may try to process these variables before the data has been retrieved. Additionally, you need all of the values to be available before you can use any of them in the wagon assembly line calculations. In this section, you create Boolean flags for each variable that you will evaluate to track whether all data has been received.
_isWagonInventoryThereFlag and data type it to the Boolean class. Assign a value of false.private var _isWagonInventoryThereFlag:Boolean = false;
_isYellowWarningDataThereFlag, _isRedWarningDataThereFlag, and _isProductionDataThereFlag and data type them to the Boolean class. Assign the value of false to all the variables.private var _isYellowWarningDataThereFlag:Boolean = false;
private var _isRedWarningDataThereFlag:Boolean = false;
private var _isProductionDataThereFlag:Boolean = false;
In each setter function, you will add the corresponding flag variable and assign its value as true signifying that the data was received by the setter function.
wagonInventory() setter function and after the current code, add the _isWagonInventoryThereFlag and set the value to true.public function set wagonInventory(_wagonInventory:ArrayCollection):void
{
this._wagonInventory = _wagonInventory;
_isWagonInventoryThereFlag = true;
}
wagonYellowWarningAmount() setter function and after the current code, add the _isYellowWarningDataThereFlag and set the value to true._wagonRedWarningAmount() setter function and after the current code, add the _isRedWarningDataThereFlag and set the value to true.wagonProductionRate() setter function and after the current code, add the _isProductionDataThereFlag and set the value to true.You will create a function to check if all the data has arrived in order to start the application.
isDataLoaded() that takes no arguments and returns a void data type.Once the conditional statement is true, you have all the data you need to populate the bin values, calculate the clock values and initialize the Timer object.
private function isDataLoaded():void
{
if (_isWagonInventoryThereFlag &&
_isProductionDataThereFlag && _isRedWarningDataThereFlag &&
_isYellowWarningDataThereFlag)
{
startProduction();
}
}
Each setter function runs independently of the others and will set its Boolean flag to true only when it receives the data from the Web Dynpro application. By calling the isDataLoaded() function from each setter function you can test whether all the data is present even if the Rich Island receives data in a different order each time.
wagonInventory() setter function, and after the current code in the function add a isDataLoaded() function. . . .
_isWagonInventoryThereFlag = true;
isDataLoaded();
isDataLoaded() function to the wagonYellowWarningAmount(), wagonRedWarningAmount(), and wagonProductionRate() setter functions.Once the application starts, if the data changes, the appropriate setter function will call the isDataLoaded() function which will call the startProduction() function. However you will only want to call the startProduction() function once because the _productionTimer variable is meant be instantiated only once, when the application is first initialized. As you recall from Part 5, the _productionTimer variable is instantiated as the Timer object that is used to animate the application. Instantiating it each time the data changes will make the Timer object reset which will cause the clock time to behave oddly.
_isYellowWarningDataThereFlag variable is declared in the Script block, create a private variable named _applicationStarted and data type it to the Boolean class and assign false to it.This flag is set to false until the application is started and then will be set to true so that another application start is not attempted.
private var _applicationStarted:Boolean = false;
startProduction() function and after the code in the function add the _applicationStarted variable and assign it a value of true. . . .
startTimer();
_applicationStarted = true;
isDataLoaded() function and in the conditional statement create another conditional statement using the NOT (!) operator to test whether the _applicationStarted variable value is false. startProduction() function.if (_isWagonInventoryThereFlag &&
_isProductionDataThereFlag && _isRedWarningDataThereFlag &&
_isYellowWarningDataThereFlag)
{
if(! _applicationStarted)
{
startProduction();
}
}
Thus far you have accounted for initial loading of data from the Web Dynpro application to the Rich Island. However, the wagon inventory data can change while the application is running if the user edits the inventory quantities in the Web Dynpro table UI element. In this case you need the Rich Island clock display, bin colors and bin quantities to update appropriately.
wagonInventory() setter function._applicationStarted Boolean value.if(_applicationStarted)
{
}
You must ensure that the application recalculates if the data changes. But you only want to call the recalculate() function after the application has been initialized because of the code sequence that must happen during this process.
if(_applicationStarted)
{
recalculate();
}
creationComplete property from the opening VBox tag.init() function and delete it. The component will be initialized when data is passed from the main application.
_wagonInventory ArrayCollection variable and remove the set value.[Bindable]
private var _wagonInventory:ArrayCollection;.
You should see the application is not populated with data.
In this tutorial you learned how to prepare a Flex application to be a Rich Island in a Web Dynpro application and how to handle asynchronous data in this scenario.
If you are interested in learning more about the topics in this tutorial, refer to About library paths in the Flex documentation.
In Part 9 you will learn how to map Web Dynpro attributes to Flex ActionScript variables. You will also learn how to create two-way communication between SAP and the rich island using a Web Dynpro event.
For your reference, here are all the parts in this series: