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.awxCreate 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:
{
public interface IFoo
{
function doFoo( text : String ) : String;
}
}
package {Here we are creating a flex module that implements the
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
{
}
}
}
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.awxThe 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.
{
public class FooImpl implements IFoo
{
public function doFoo( text : String ) : String
{
return "foo::"+text;
}
}
}
Create the main application as a flex project.
<?xml version="1.0" encoding="utf-8"?>Here in the main application, we create an instance of the
<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>
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.
9 comments:
Nice Explanation
I really like this coupling between Flex and OSGi technology. OSGi specifically lacks a UI to allow it to work as plumbing in the maximum number of devices.
However, unfortunately you are using something that is not OSGi. It is kind of confusing to call it OSGi when it is something like the OSGi Framework. The power of a specification is that it promotes interoperability, "like" is a four letter word in this context :-)
It is also dangerous for the OSGi Alliance because with current trademark laws we could loose the trademark if we do not limit this kind of use.
Could you explain why you could not use OSGi as it is?
Kind regards,
Peter Kriens
Hi,
You may be interested in Solstice which is a platform for modular rich internet applications using OSGi for the server technology and Flex for the UI technology.
Cheers,
Chris
You are right Peter, it is "like" the OSGi spec and interfaces. It would be interesting to implement the real OSGi spec in AS3 - the lack of threads would be a challenge - but could be a blessing ! BTW - this is a pure client side operation - we are taking advantage of Flex modules to "implement" loaded bundles. The fact that all that could be done in the flash player on the browser is pretty cool.
where can i find AWX swc?
ArcWebServices, which includes ArcWebExplorer (AWX) are not publicly available anymore :-( One of these days, will have to migrate the OSGi-ish portion to the new Flex API for AGS (http://resources.esri.com/arcgisserver/apis/flex/) - Should not be to hard :-)
I really want to understand how this approach can be usefull and so far I have two questions:
1. If bundle FooBundle implements some UI component (extends not ModuleBase but Module class), how application can access it after "loadFoo()" call? How application can include loaded module into it's UI?
2. How application whould know that bundle is loaded and it's time to call "doFoo()" for instance?
It has been a while - but I can think of the following:
Using Module that implements the IBundleActivator using start function, you can add a UI component to the stage.
Once FooModule is loaded - using the context, you can publish a service availability
The above code does not show this - but (at the time) there a way to register with the context to be notified of new services - kust like OSGi.
Would love to revive that project - it has been year - must have the code somewhere in SVN.
When a create the ActionScript Project and the class "FooBundle.as" a have two errors and can't generate the .SWC.
* Error 1: 1172: The definition mx.core: FlexVersion was not found.
* Error 2: 1172: The definition mx.preloaders: SparkDownloadProgressBar was not found.
Post a Comment