Adobe
Products
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
Student and Teacher Editions
More products
Solutions
Creative tools for business
Digital marketing
Digital media
Education
Financial services
Government
Web Experience Management
More solutions
Learning Help Downloads Company
Buy
Home use for personal and home office
Education for students, educators, and staff
Business for small and medium businesses
Licensing programs for businesses, schools, and government
Special offers
Search
 
Info Sign in
Welcome,
My cart
My orders My Adobe
My Adobe
My orders
My information
My preferences
My products and services
Sign out
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out My orders My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
Qty:
Purchase requires verification of academic eligibility
Subtotal
Review and Checkout
Adobe Developer Connection / Flex Developer Center /

Accessing remote shared objects from Flex with WebORB .NET

by Damian M. Piccolo

Damian M. Piccolo
  • www.andensolutions.com

by Esteban Yofre

Esteban Yofre
  • www.andensolutions.com

Content

  • About Remote Shared Objects
  • Writing the server-side code
  • Configuring WebORB
  • Writing the ActionScript code

Created

28 March 2011

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
collaboration Flash Builder Flex shared objects WebORB

Requirements

Prerequisite knowledge

To make the most of this tutorial you’ll need previous experience building applications with Adobe Flash Builder as well as some knowledge of development techniques using .NET and Microsoft Visual Studio.

User level

Intermediate

Required products

  • Flash Builder 4 (Download trial)

Sample files

  • WebORB_RSO.zip

Additional required other products

  • WebORB for .NET v4.2
    • Download
    • Learn more
  • Microsoft Visual Studio
  • Internet Information Services (running .NET Framework 2 or above)

In this tutorial you’ll learn about Remote Shared Objects (RSOs) and how to use them from either the client or server side. You’ll also develop a small application based on a simple word game that will access and modify RSOs using from client-side (ActionScript) and server-side (C#) code using the WebORB Integration Server to marshal the communications between client and server. You’ll need to have an IIS server running and WebORB installed on your server.

About Remote Shared Objects

RSOs track, store, share, and synchronize data between multiple client applications.

An RSO is an object that lives on the server. It resides in the scope of a messaging application that clients connect to. More than one client can connect to an RSO, and all of them will have access to the data in the RSO. WebORB, in this case, is responsible for managing the RSO and providing access to it for various clients.

RSOs are particularly useful when they are used on several clients at the same time. When one client changes data that updates the RSO on the server, the server sends the change to all other connected clients, enabling you to synchronize many different clients with the same data. RSOs can also be updated and accessed by the server, giving developers more options for application development.

To sum it up, RSOs can be used to:

  • Synchronize data of any type automatically, for example, in a collaborative web application.
  • Send a message to all clients connected to the same room, for example, in a chat application.

In this tutorial, you will use RSOs to create a simple online version of the Add-a-word game. The object of this game is to add a word to a sentence, one user at a time, and eventually come up with a very long sentence (that still makes sense).

Consider the following example:

  • Two connected users begin a game of Add-a-word.
  • The application assigns turns to each of the connected users.
  • User 1 starts the game by typing "My" and clicking Submit. Once User 1 submits a word, it is the next user’s turn. The application automatically disables the submit button for the first user, and enables it for the next user.
  • User 2 types "house" and clicks Submit, passing control back to User 1.
  • User 1 types "is", and so on.
  • During the game, the RSO keeps track of the content of the sentence. At this point it will read "My house is".

Writing the server-side code

The server-side code for this application keeps track of all connected users, assign turns, and add words to the sentence.

Note: The code snippets included in the steps below are not complete; rather they are used to illustrate the main concepts in the server-side implementation. For the complete code, see WeborbSharpRSO.cs in the sample files for this tutorial.

Follow these steps to create the server-side DLL:

  1. Create a Class Library project in Microsoft Visual Studio.
  2. In the project, add a reference to the Weborb.dll. This library is located in the bin folder in your WebORB installation folder.
  3. Create the main class, in this case, named WeborbSharpRSO. This class extends Weborb.Messaging.Server.Adapter.ApplicationAdapter, which lets you create WebORB applications:
namespace WeborbSharpRSO { public class WeborbSharpRSO : ApplicationAdapter { } }

The ApplicationAdapter class has several methods that let you know when an application is started, when a new room is created, and when a client connects or disconnects. An application can have several rooms running simultaneously. Each room may have one or more clients connected and sharing information. Clients connected to one room share information only with other clients in the same room.

For this example you’ll use the following two methods to detect when a client joins or leaves a room:

public override bool roomJoin(IClient client, IScope room) public override void roomLeave(IClient client, IScope room)
  1. Declare the Remote Shared Object name at the top of your class:
public string sharedObjectName = "addWord";
  1. In the roomJoin() method, first check if the user can connect to the room. Then check if the room has the Remote Shared Object. If not, create it and add a SharedObjectListener to it. This listener will detect any changes in the RSO.
public override bool roomJoin(IClient client, IScope room){ if (base.roomJoin(client, room)) { ISharedObject so; if (!hasSharedObject(room, sharedObjectName)){ createSharedObject(room, sharedObjectName, false); so = getSharedObject(room, sharedObjectName); so.addSharedObjectListener(new MySharedObjectListener()); } else so = getSharedObject(room, sharedObjectName); … } }

Note: The code in roomJoin could also be placed inside of the appStart method.

The next step is to check and update the values of some attributes of the RSO, such as the number of users connected and whose turn is next. These attributes hold all the information you want to share across clients.

For example, your code will get the existing number of users connected to the room from the shared object (SO) and then increment that number by one. This value is then written back to the SO:

if(so.hasAttribute("totalUsers")) totalUsers = so.getLongAttribute("totalUsers"); totalUsers++; … so.setAttribute("totalUsers", totalUsers);

In addition to totalUsers, the RSO shares the following data:

  • userList: List of all the clients connected to the same room
  • currentUser: id and name of the client whose turn it is to add the next word
  • sentence: the actual sentence being formed
  • word: the last word submitted

    Each client that connects to a room is assigned unique ID based on the connection order.

  1. To finish up the roomJoin() function, add the following code, which sends this ID to the client using the invokeClients method (explained in more detail below):
object[] args = new Object[] {client.getId()}; invokeClients("SetUserId", args, client.getConnections(room));
  1. Next, add the Listener class implementing Weborb.Messaging.Api.SO.ISharedObjectListener interface:
public class MySharedObjectListener : ISharedObjectListener { }

This class provides methods that can be used to check for different types of changes on the shared object. This tutorial focuses on the onSharedObjectUpdate() method, which is used to check for changes on the remote object. A change on the word attribute of the RSO invokes a method that will process the information and set the next user.

  1. Update onSharedObjectUpdate() as follows:
public void onSharedObjectUpdate(ISharedObjectBase so, string key, object value){ if (key == "word") WeborbSharpRSO.nextUser(so, value.ToString()); }

The nextUser() method is called when there’s a new word to add to the sentence. Even though you could modify the RSO directly in this function, do not use this approach.

When the server-side code changes the RSO during a client-side request, the client that initiated the request does not get the changes added by the server. The server-side accumulates all the changes as independent events. The accumulated events are sent out to the original sender first and then to all other subscribers. Each event has a corresponding RSO version number. If there are multiple change events all going out with the same version number, Flash Player lets only the first one through. This will cause the client that initiated the request to get only the changes it requested, not the changes added by the server to the RSO on the same request.

  1. To address this, start a new thread where the actual server-side RSO changes will take place:
public static void nextUser(ISharedObjectBase so,string word) { ThreadPool.QueueUserWorkItem(ChangeCurrentUser, new object[] {so, word}); }
  1. Add a ChangeCurrentUser() function to actually change the RSO on the server. Here’s where you add the word to the sentence and write it back to the RSO:
public static void changeCurrentUser( object state ){ … if( word != "" ){ string text = ""; if( so.hasAttribute("sentence") ) text = so.getStringAttribute("sentence"); so.setAttribute("sentence", text += " " + word); } … }
  1. Use this same function to identify who the next user is and then write that information back to the RSO too.
so.setAttribute("currentUser", newCurrentUser.ToString() );
  1. Add the roomLeave() method to handle clean-up tasks when a user leaves the room. This method updates the list of clients still playing the game.
  2. Note the three-step process: the content of the userList attribute is retrieved and set to the users dictionary, the client that is leaving the room is removed from the dictionary, and then a copy of the content of this object is put into a newUsers dictionary. The reason behind this awkward process is that the server won’t detect the change on the original users object when an element is removed. As a result, if you send back the same object to the RSO, the changes will not be sent to the clients.

users = so.getMapAttribute("userList"); … if (users.Contains(client.getId())) users.Remove(client.getId()); newUsers = new Dictionary<string, string>(); foreach (DictionaryEntry de in users) newUsers[de.Key] = de.Value; … so.setAttribute("totalUsers", totalUsers);
  1. Lastly, add the invokeClients() to the main class. This function uses the connection.invoke method to call ActionScript methods on the client. You will need to pass the name of the method to call, any needed parameters, and the list of client connections. The name used in the functionName variable must exist as a function name in the client application:
private void invokeClients(string functionName, object[] args, IList<IConnection> ILconn ){ foreach(IConnection conn in ILconn){ ((IServiceCapableConnection)conn).invoke(functionName, args); } }

A detailed explanation of the invoke() method is outside of the scope of this tutorial. For more information about this method please consult the WebORB documentation or see Invoke ActionScript functions from .NET.

  1. Once you have finished coding the class, build the DLL and copy it to the bin directory inside the WebORB folder.

Configuring WebORB

You’ll need to configure WebORB before your application will work. Specifically, you need to add a messaging application so WebORB is aware of its existence and can manage the user connections. Follow these steps:

Open the WebORB management console (see Figure 1) using a web browser. If you installed WebORB using the default settings, the console is available at: http://localhost/weborb4/weborbconsole.html

The WebORB management console
Figure 1. The WebORB management console.
  1. Click the Messaging Server tab to begin creating a new messaging application.
The Messaging Server tab
Figure 2. The Messaging Server tab.
  1. Select Applications under WebORB Messaging Server (see Figure 2) and then click the Add Application button (the green plus sign ("+") button).
  2. In the Application Editor pop-up window, type MyRSO as the application name and then select WeborbSharpRSO.WeborbSharpRSO as the Application Handler (see Figure 3).
Setting up the application
Figure 3. Setting up the application.
  1. Click Save. Your application will be listed in the list of applications.
  2. Browse your hard drive, and locate the folder named MyRSO inside the {weborb4 path}\Applications\ folder. Verify that the MyRSO folder contains a file named App.config.

Note: If the MyRSO application doesn’t show up under the list of applications, but you can see the folder in the hard drive, you may need to restart IIS and then reload the WebORB console.

If you cannot see the MyRSO folder in your hard drive you may need to check your permissions. For more information on permissions, refer to the WebORB installation and deployment documentation available through the Help/Resources tab of the WebORB console.

Writing the ActionScript code

With the server-side code in place, you’re ready to open Adobe Flash Builder and develop the ActionScript code.

Note that you could have made many of the changes to the RSO directly with ActionScript using WebORB’s own SharedObjectsApp messaging application. This tutorial used a more convoluted path to illustrate RSO access and modification from the server.

Note: The code snippets included in the steps below are not complete; rather they are used to illustrate the main concepts in the client-side implementation. For the complete code, see WeborbRSO.mxml in the sample files for this tutorial.

To create your ActionScript code, follow these steps:

  1. Start by creating a new Flex Project in Flash Builder (choose File > New > Flex Project).
  2. Set up a basic application with two states: login and game:
<s:states> <s:State name="login" /> <s:State name="game" /> </s:states>
  1. Add code for the login state, which comprises a TitleWindow with two textInput controls (Room Name and User Name) and a Connect button:
<s:TitleWindow includeIn="login" verticalCenter="0" horizontalCenter="0" width="300" height="180" > <s:layout> <s:VerticalLayout gap="5" verticalAlign="middle" horizontalAlign="center" /> </s:layout> <s:HGroup verticalAlign="middle"> <s:Label text="Room Name:" width="80" textAlign="right" /> <s:TextInput id="txtRoomName" text="Test1" width="150" /> </s:HGroup> <s:HGroup verticalAlign="middle"> <s:Label text="Your Name:" width="80" textAlign="right" /> <s:TextInput id="txtYourName" text="Damian" width="150" /> </s:HGroup> <s:Button label="Connect" click="onConnect()" /> </s:TitleWindow>
  1. Add code for the game state, which comprises an HGroup that displays a list of the connected users on the left, the sentence the users are forming on the top right, and a textarea control where the users can type the next word at the bottom right:
<s:HGroup includeIn="game" verticalCenter="0" horizontalCenter="0"> <s:TitleWindow title="User List ({totalUsers})" width="150" height="300"> <s:List id="lUsers" dataProvider="{userList}" labelField="Name" width="100%" height="100%"> <!-- We use an item renderer to color red the name of the current user --> <s:itemRenderer> <fx:Component> <s:ItemRenderer height="20"> <s:Label id="myLabel" width="100%" verticalCenter="0" text="{data.name}" color="{data.userId==data.current?0xff0000:0x000000}"/> </s:ItemRenderer> </fx:Component> </s:itemRenderer> </s:List> </s:TitleWindow> <s:TitleWindow title="Add a Word -- {userName} -- User Id:{userId}" width="500" height="300"> <s:layout> <s:VerticalLayout verticalAlign="middle" horizontalAlign="center" /> </s:layout> <s:TextArea editable="false" selectable="false" width="450" height="200" text="{text}" /> <s:HGroup id="hgSendText" gap="10" horizontalAlign="center" verticalAlign="middle" enabled="{userId==currentUser?true:false}"> <s:TextInput id="txtAddText" width="400" /> <s:Button label="Add Word" click="onSendText()" /> </s:HGroup> </s:TitleWindow> </s:HGroup>

The Connect button in the login state invokes the onConnect() function. This function connects to the server and obtains the remote shared object.

  1. Add onConnect() to the block:
public function onConnect():void{ roomName = txtRoomName.text; userName = txtYourName.text; SharedObject.defaultObjectEncoding = ObjectEncoding.AMF0; /** * Establish connection * */ nc = new NetConnection(); nc.client = this; nc.objectEncoding = ObjectEncoding.AMF0; nc.addEventListener( NetStatusEvent.NET_STATUS, onNetStatus ); nc.connect( urlServer + "/" + weborbApplicationName + "/" + roomName ); /** * Get Remote Object * */ so = SharedObject.getRemote( sharedObjectName, nc.uri, false ,false); so.client = this; so.addEventListener( SyncEvent.SYNC, onSync ); so.connect( nc ); }

The server URL, name of the WebORB application, and name of the remote object are previously declared in variables. The name of the chat room is obtained from the login window. Users can login to different chat rooms to work on different sentences.

  1. Add the setUserId() function, which is called from the server at the end of the connection process. Use this function to save the userID of the client so you can match it to the username. This function also changes the application’s state from login to game.
public function setUserId(userId:String):void { this.userId = userId; this.currentState="game"; setName = true; }
  1. Add the onSync() function, which is called each time there’s a sync event on the remote shared object. Use this function to set the client’s name the first time they login. Also use this function to enable/disable the button to submit text as well as to update the list of users logged in. Each time there is a change, this function creates the list and sets the id of the user whose turn it is. (See WeborbRSO.mxml for the full implementation.)
  2. Finally, add the onSendText() function, which send the word to the server. This function is called when the user clicks the Add Word button. It simply sets the word property on the shared object.
public function onSendText():void { so.setProperty("word",txtAddText.text); txtAddText.text = ""; }
  1. Build the application and try it out!

Where to go from here

This add-a-word game is just a simple application that showcases some of the possibilities of Remote Shared Objects. Of course, there are several ways to improve this application. To start with, you could limit the content sent by a user to just one word, and not allow any number of words. You could also use the RSO to keep track of several sentences at a time inside the same room if you wanted.

This tutorial demonstrated that RSOs can be used in many different situations, ranging from sharing information between clients to managing and synchronizing real-time online games. Now that you’re familiar with them, you can adapt these techniques for your own applications.

You can try this application at Anden Solutions.

For more information about WebORB for .NET visit its overview page.

Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License+Adobe Commercial Rights

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

More Like This

  • Using automated tools across the lifecycle to develop higher quality Flex applications
  • Flex mobile development tips and tricks – Part 1: Data handling
  • Pushing data from a Flex publisher client to a consumer client with WebORB for .NET, Apache NMS, and ActiveMQ
  • Data push from .NET to Flex with MSMQ
  • Building a data-driven Flex and Java application with WebORB for Java
  • ActionScript and .NET client-server class mappings
  • Yahoo! Maps collaboration using Flex and BlazeDS
  • Using an ActionScript code generator to enable Flex and .NET integration
  • Integrating Flex applications with NHibernate

Tutorials & Samples

Tutorials

  • Flex mobile performance checklist
  • Flex and Maven with Flexmojos – Part 3: Journeyman
  • Migrating Flex 3 applications to Flex 4.5 – Part 4

Samples

  • Twitter Trends
  • Flex 4.5 reference applications
  • Mobile Trader Flex app on Android Market

Flex User Forum

More
07/25/2011 Flash Player Debug Issues - Safari 5.1 & Chrome 13
04/22/2012 Loader png - wrong color values in BitmapData
04/22/2012 HTTPService and crossdomain.xml doesn't work as expected
04/23/2012 Memory related crashes in Flex application

Flex Cookbook

More
04/06/2012 How to detect screen resize with a SkinnableComponent
02/29/2012 Embed Stage3D content inside Flex application components
02/15/2012 Custom WorkFlow Component
02/09/2012 Using Camera with a MediaContainer instead of VideoDisplay

Products

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • Mobile Apps
  • Photoshop
  • Touch Apps
  • Student and Teacher Editions

Solutions

  • Digital marketing
  • Digital media
  • Web Experience Management

Industries

  • Education
  • Financial services
  • Government

Help

  • Product help centers
  • Orders and returns
  • Downloading and installing
  • My Adobe

Learning

  • Adobe Developer Connection
  • Adobe TV
  • Training and certification
  • Forums
  • Design Center

Ways to buy

  • For personal and home office
  • For students, educators, and staff
  • For small and medium businesses
  • For businesses, schools, and government
  • Special offers

Downloads

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Security
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy Policy and Cookies (Updated)

Ad Choices

Reviewed by TRUSTe: site privacy statement