The UcompOS Event Propagation Model

The other day, I wrote a blog posting describing how the UcompOS RPF implements the MVC design pattern.

This implies that there is an event-driven architecture that has been facilitated in the UcompOS Continuum and that is indeed the case.

In this blog posting, we have to roll our sleeves up and really dig into the UcompOS SDK so that I can help you understand how the UcompOS RPF Event Architecture works.  If you have full command of the UcompOS RPF’s event architecture, it will help you build the most engaging and interactive rich experiences for your Rich Portal Applications.

The architecture at first glance is necessarily complex and involved and this will probably likely be just one of many blog postings I’ll make in reference to this topic and as time passes, I am going to work hard to make the event architecture simpler, more transparent, and as close as possible to best practice.  Of course developer feedback will be a crucial part of that mission.

CommandObject Transactions

If you’ve read my other postings, you have a very basic understanding of Proxy Components and Services Dictionaries.

Simply put, a UcompOS entity exposes its internal functionality to other UcompOS entities by publishing a Services Dictionary and a UcompOS entity contacts functionality in another entity by using a Proxy Component.

By strict convention, ALL communication between entities in the UcompOS Continuum should occur via the SDK class SDKClient and its send(); method.  (NOTE: There is a very esoteric exception to this that is handled behind the scenes by the UcompOS RPF that would involve two UcompOS entities participating in drag and drop interactions but that is beyond the scope of my article here and will be covered in an upcoming tutorial.)

The UcompOS SDK has both client and server infrastructure implemented.  Therefore, each UcompOS entity is capable of serving both as a server capable of receiving commands from other entities as well as a client capable of sending commands to other entities simultaneously.

The UcompOS RPF implements an asynchronous event dispatchment model.

When an entity needs to access a public API command in another entity, it (usually with the assistance of a Proxy Component) creates a CommandObject instance that is packaged into a DataPackage instance and sends it to the target entity via the SDKClient send(); method.  All these details are masked by the call(); method of AbstractProxyComponent which all Proxy Components must inherit from.

The server(); method of the SDKServer class is the first spot in the target entity to come in contact with the DataPackage.

DataPackages sent across the SDK Tunnel are encoded into compressed ByteArrays.

The server implementation in the SDK decodes the DataPackage and passes it to one of a couple different polymorphic constructs in the SDK:  CommandObjectHandler or EventObjectHandler

In the scenario where one entity is contacting the public API method of another entity, the DataPackage will contain a CommandObject and thus the DataPackage will be passed to the CommandObjectHandler in the SDK.

This will pass the data Object to the internal implementation code in the target entity.

By strict convention, any method that is capable of being targeted by another entity must accept exactly one parameter of type Object and return an item of type Object.

In order to understand the full event cycle in the UcompOS RPF, we must study what happens when this public API method returns this Object.  Where does this Object go from here?  How does it get back to the calling entity?

CommandObjectHandler passed the DataPackage to the internal implementation method and is returned the Object return from the method.

At this point, CommandObjectHandler turns from a server implementation to a client implementation and it creates a new DataPackage, puts an EventObject instance into it, and then sends the DataPackage back to the original entity.  So the original entity then becomes a server.

When the DataPackage with the EventObject packaged into it gets back to the SDKServer implementation in the calling entity, it is passed to the EventObjectHandler class.

The EventObjectHandler class then passes it to any event handlers that have been attached to the Proxy Component that made the initial public API call in the first place.

This is in fact why AbstractProxyComponent, which all Proxy Components extend from, inherits from EventDispatcher – so we can implement addEventListener(); thus implementing a paradigm many Flex and Flash coders are much more accustomed to.

When a public API method returns its required Object, an eventType property can be set to it.  If you do not explicitly set this, then CommandObjectHandler will set this for you as the constant SDKEvent.COMPLETE.

This eventType property is important as it has implications as far as how events get passed to a Proxy Component’s event handlers.

Suppose I have the following Services Dictionary class in a UcompOS application:

package
{
 
  import com.ucompass.ucompos.sdk.server.AbstractServicesDictionary;
 
  public class ServicesDictionary extends AbstractServicesDictionary
  {
    _map =
    {
      'Greeting.sayHello':
      {
 
        static:true,
        classRef:api,
        method:'sayHello',
        description:'Returns a greeting'
      }
 
    };
 
  }
 
}

Let’s suppose I have the following public API method that maps to Greeting.sayHello in my Services Dictionary example above:

public static function sayHello(data:Object):Object
{
  return {eventType:"Hello",greeting:"Hello there, "+data.name+"!"};
}

Now let’s suppose my Proxy Component located in another entity that will contact the Greeting.sayHello method above looks something like this:

package
{
 
  import com.ucompass.ucompos.sdk.client.AbstractProxyComponent;
  import com.ucompass.ucompos.sdk.model.SDKModel;
 
  public class Greeting extends AbstractProxyComponent
  {
 
    public function Greeting()
    {
      super._destination = SDKModel.getInstance().parent;
    }
 
    public function getGreeting(name:String):void
    {
      call("Greeting.sayHello",{name:name});
    }
 
  }
 
}
}

In my entity that will call Greeting.sayHello, I may see the following:

var g:Greeting = new Greeting();
g.getGreeting("Edward");

Now how do I get the greeting back from the entity that is exposing the public API method Greeting.sayHello?

Because AbstractProxyComponent extends EventDispatcher, and because my Greeting Proxy Component extends AbstractProxyComponent (a strict requirement of all Proxy Components), I can add an event listener to it.

g.addEventListener("Hello",greetingHandler);
 
private function greetingHandler(event:SDKEvent):void
{
  var greeting:String = event.data.greeting;
}

Notice my event handler is passed an instance of SDKEvent.  This is universal for all Proxy Components.

The SDKEvent instance will have a data property which will be the data Object returned by the remote public API method in the contacted entity.

Therefore, the eventType property in the return Object of a public API method determines which Proxy Component event handlers are passed an SDKEvent instance.

UcompOS Continuum Events

The above example shows a very simple example of an asynchronous request-response phase of a Proxy Component – public API method transaction.

There is another type of event in the UcompOS RPF called a Continuum Event.

The UcompOS Portal sponsors a public API method named GlobalManager.dispatchEvent.  This is accessed through the UcompOSGlobalManagerProxy Singleton class in the UcompOS SDK and its dispatchContinuumEvent(); method which accepts as input two parameters: type:String, and data:Object

When this method is accessed, every entity in the entire UcompOS Continuum is dispatched the event.

The implications of this is that you can monitor activity across the boundaries of different applications.  For instance, maybe you have a UcompOS Chat Application and when you receive an instant message from an individual user, you automatically want a separate UcompOS Address Book Application to open to that user’s Address Book entry.

Targeted EventObject Instances

The BroadcastEvent Singleton class in the UcompOS SDK has a dispatchEvent(); method.  This lets you send an EventObject on the fly to a single target entity.

For instance, the UcompOS SDK has a Proxy Component, that is the interface to various public API methods in the UcompOS Portal, called UcompOSWindowProxy.  The UcompOSWindowProxy‘s add(); method attaches an MDI window to the UcompOS Portal.

Internal to the UcompOS Portal implementation, it wants to notify the entity that created the UcompOS Window instance when certain user-driven activities occur such as when the window is moved, closed, minimized, maximized, etc.

Let’s look at a very simple example with some code.

Let’s suppose I have a UcompOS Application and I want to create a UcompOS Window, then I want to know when the user has closed the window.

In my application, the code I’d use to form the UcompOS Window could look like this:

var w:UcompOSWindowProxy = new UcompOSWindowProxy();
w.add("http://desktop.ucompass.com/MySubApp.swf","My Sub Application",500,500,100,100);

This will load the content at http://desktop.ucompass.com/MySubApp.swf into a UcompOS Window of dimensions 500 x 500 positioned at (100,100) from the upper-left origin point of the UcompOS Portal.

Now suppose I want to know when that window has closed.

No problem:

w.addEventListener(UcompOSWindowProxy.CLOSE,closeHandler);
private function closeHandler(event:SDKEvent):void
{
 // the window has closed
}

The reason why this works this way is that internal to the UcompOS Portal, there is a call to the UcompOS SDK static method BroadcastEvent.dispatchEvent(); that dispatches an EventObject (encapsulated in a DataPackage of course) to the entity that created the UcompOS Window.

As another example, consider the UcompOSMenuBarProxy class.  I haven’t covered the UcompOS Menu Bar in any tutorials quite yet, but the UcompOSMenuBarProxy class has a setMenuBar(); method that lets you attach an XML model that will be used as the dataProvider for the Menu Bar on the UcompOS Portal while the application in scope is in focus.

You could do something like this:

var menuModel:XML = new XML("<menu><menuitem label='File'><menuitem label='Open' data='1'/><menuitem label='Close' data='2'/></menuitem></menu>");
var m:UcompOSMenuBarProxy = UcompOSMenuBarProxy.getInstance();
m.setMenuBar(menuModel);
m.addEventListener(UcompOSMenuBarProxy.CHANGE,menuBarHandler);
 
private function menuBarHandler(event:SDKEvent):void
{
 var chooseString:String = "User chose "+event.data.label+" whose data property is "+event.data.data;
}

Summary

The event architecture in the UcompOS RPF is indeed complex at first glance.  There is no getting around that.  I am going to continue to work to simplify it, improve the documentation surrounding it, and get the implementation details as close as possible to a true best practice MVC implementation.

About Edward Mansouri
Edward Mansouri is the CEO and Founder of Ucompass.com, Inc., a company focused on building scalable and profitable e-Learning enterprises. His expertise is in building e-Learning software, as well as in building visual frameworks such as the Enrich Content Enrichment System and the newly announced UcompOS Rich Experience Framework. He has been working with Flash since 1998, building Flash applications since 2002, and working with Adobe AIR since its private alpha release in 2006. He authored the site AIRApps.net (later renamed to O2Apps.com) dedicated to providing leadership in building Adobe AIR applications. In 2010, he is building and releasing a new e-Learning platform called Educator 2 which is built entirely upon the UcompOS Rich Experience Framework. Since 1999, over 1,000,000 students have taken courses served with his original e-Learning platform, Educator 1.

Comments are closed.