Showing posts with label Flex OSGi. Show all posts
Showing posts with label Flex OSGi. Show all posts

Wednesday, October 17, 2007

Flex and OSGi

The AWX framework is based on a simplified OSGi implementation in AS3. The advent of flex modules made this implementation possible. The following is a simple walk-through that showcases how to use this solution. The idea is to define an interface whose implementation can be defined and discovered at runtime. Using FlexBuilder as a project manager makes things a bit easier.

Create a flex library project named "FooAPI" to define the following interface. A SWC "FooAPI.swc" is generated upon the build in the "bin" directory.
package com.esri.awx
{
public interface IFoo
{
function doFoo( text : String ) : String;
}
}

Create a flex actionscript project named "FooBundle" - make sure to add the AWX swc as a project library and the "FooAPI" project. Modify the FooBundle.as class as follows:
package {
import com.esri.aws.osgi.framework.IBundleActivator;
import com.esri.aws.osgi.framework.IBundleContext;
import com.esri.awx.FooImpl;
import com.esri.awx.IFoo;

import flash.utils.getQualifiedClassName;

import mx.modules.ModuleBase;

public class FooBundle extends ModuleBase implements IBundleActivator
{
public function start( context : IBundleContext ) : void
{
context.registerService( getQualifiedClassName(IFoo), new FooImpl());
}

public function stop( context : IBundleContext ) : void
{
}
}
}
Here we are creating a flex module that implements the IBundleActivator interface that defines the start and stop functions. In the start fnction implementation, we register a FooImpl instance with the framework. The value of getQualifiedClassName(IFoo) (Notice, we are using the IFoo interface) is acting as a key, that we can use in other bundles to get a reference to the IFoo implementation.
package com.esri.awx
{
public class FooImpl implements IFoo
{
public function doFoo( text : String ) : String
{
return "foo::"+text;
}
}
}
The compilation of this project will output a FooBundle.swf file. This is the bundle (in OSGi parlant) that we will load dynamically at runtime. Make sure that you set the output of the project to a web application. This will facilitate the following step.

Create the main application as a flex project.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:awx="http://www.arcwebservices.com/2007/awx"
layout="horizontal"
>
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import com.esri.awx.IFoo;
import flash.utils.getQualifiedClassName;
import com.esri.aws.osgi.framework.IServiceReference;
import com.esri.aws.osgi.framework.IBundle;
import com.esri.aws.osgi.framework.IBundleContext;
private function listBundles() : void
{
trace( "---Bundles---");
var context : IBundleContext = framework.systemContext;
for each ( var bundle : IBundle in context.getBundles())
{
trace( bundle.getBundleID()+" "+bundle.getSymbolicName());
}
}
private function loadFoo() : void
{
framework.installBundle("http://host/webapp/FooBundle.swf");
}
private function doFoo() : void
{
var context : IBundleContext = framework.systemContext;
var ref:IServiceReference = context.getServiceReference(getQualifiedClassName(IFoo));
if( ref == null)
{
Alert.show( "No reference to service IFoo");
}
else
{
var foo : IFoo = context.getService( ref ) as IFoo;
trace( foo.doFoo( "Hello"));
}
}
private function uploadFoo() : void
{
var bundleID : int = -1;
var context : IBundleContext = framework.systemContext;
for each ( var bundle : IBundle in context.getBundles())
{
if( bundle.getLocation() == "http://host/webapp/FooBundle.swf")
{
bundleID = bundle.getBundleID();
break;
}
}
if( bundleID != -1)
{
context.getBundle(bundleID).uninstall();
}
}
]]>
</mx:Script>
<mx:TraceTarget/>
<awx:Framework id="framework" apiKey="xxxxxxx"/>
<mx:Button label="List Bundles" click="listBundles()"/>
<mx:Button label="Load Foo" click="loadFoo()"/>
<mx:Button label="Do Foo" click="doFoo()"/>
<mx:Button label="Upload Foo" click="uploadFoo()"/>
</mx:Application>
Here in the main application, we create an instance of the Framework.
The listBundles function lists all the available bundles. By default, the framework installs the system bundle and an authentication bundle.
The loadFoo function installs the foo bundle from a url.
The unloadFoo function unloads the bundle from the framework, which automagically unregisters any registered services.
The doFoo function demonstrates how to get a reference to an IFoo implementation. If the reference is null then the service was not loaded or was unloaded. if we have a non-null reference value, then we use it to get a service reference, that we can safely cast to IFoo and act upon it.