Archive for August, 2010
NativeApplicationUpdater – updater for AIR apps packaged with native installers
I just released on Google Code a new project called NativeApplicationUpdater. Basically the name explains its purpose but for those that don’t know, AIR 2.0 brings new capability of packaging applications with native installers. This is necessary when you want to use the new NativeProcess APIs. Unfortunately Update Framework that comes with AIR 2.0 SDK doesn’t bring yet capability of updating this type of applications. That is why I decided to build it myself and publish it as open source library.
Here is a video explaining how it works:
Swiz 1.0 Chaining API explained
Yesterday I was tasked to find the best way to bootstrap a Flex application that uses Swiz 1.0 RC1. The challenge was to initialize application controllers and data model in the right sequence. This is an AIR application so it had to initialize data from an SQLite database, make few calls to remote services to check for data updates and do couple of other things before user could actually see first screen. My initial thought was to create a StartupController that would invoke the proper functions in a right order. That was a good initial direction but things started to get more difficult when I had to deal with async remote calls and local async APIs such as the one from the SQLite database.
So my next thought was, why not to try the new Chaining API that comes with Swiz? After my first look at the documentation I wasn’t really sure how I should approach it but after more digging I managed to figure it out
Here is what I did. I kept my StartupController with its init function that gets called after the controller is constructed and all its dependencies are injected. This was ensured by the [PostConstruct] metadata that comes with latest version of Swiz. Next that function creates a chains of function calls, remote invocations and events that bootstrap my application.
This is my StartupController where everything starts:
package controllers { import delegates.RemoteServiceDelegate; import flash.events.IEventDispatcher; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import org.swizframework.events.ChainEvent; import org.swizframework.utils.chain.AsyncCommandChainStep; import org.swizframework.utils.chain.ChainType; import org.swizframework.utils.chain.CommandChain; import org.swizframework.utils.chain.EventChain; import org.swizframework.utils.chain.EventChainStep; import org.swizframework.utils.chain.FunctionChainStep; public class StartupController { [Dispatcher] public var dispatcher:IEventDispatcher; [Inject] public var remoteServiceDelegate:RemoteServiceDelegate; [PostConstruct] public function init():void { // Initializing sequential CommandChain, that will stop on errors var commandChain:CommandChain = new CommandChain(ChainType.SEQUENCE, true); // Registering event listener when chain execution is complete commandChain.addEventListener(ChainEvent.CHAIN_COMPLETE, commandChainComplete); // Registering event listener in case chain execution fails commandChain.addEventListener(ChainEvent.CHAIN_FAIL, commandChainFail); // Adding async chain step that invokes remote AMF service commandChain.addStep( new AsyncCommandChainStep( remoteServiceDelegate.ping, ["ping param value"], pingResultHandler, pingFaultHandler)); // Adding function step that calls local function commandChain.addStep(new FunctionChainStep(this.localFunction)); // Initializing parallel event chain that will be nested in command chain var eventChain:EventChain = new EventChain(dispatcher, ChainType.PARALLEL, true); // Registering event listener when event chain execution is complete eventChain.addEventListener(ChainEvent.CHAIN_COMPLETE, eventChainComplete); // Registering event listener in case chain execution fails eventChain.addEventListener(ChainEvent.CHAIN_FAIL, eventChainFail); // Adding event chain step that will dispatch INIT_PERSISTENCE event, // this event is mediated in PersistenceController eventChain.addEvent(new EventChainStep("INIT_PERSISTENCE")); // Adding event chain step that will dispatch INIT_SOMETHING_ELSE event, // this event is NOT mediated anywhere, this just for example and better understanding // eventChain.addEvent(new EventChainStep("INIT_SOMETHING_ELSE")); // Nesting event chain in parent command chain commandChain.addStep(eventChain); // Starting whole command chain commandChain.start(); } private function localFunction():void { trace("Running localFunction"); } public function pingResultHandler(event:ResultEvent):void { trace("Received result from remote ping call:", event.result); } public function pingFaultHandler(event:FaultEvent):void { trace(event.fault.faultDetail); } private function commandChainComplete(event:ChainEvent):void { trace("CommandChain complete"); } private function eventChainComplete(event:ChainEvent):void { trace("EventChain complete"); } private function commandChainFail(event:ChainEvent):void { trace("CommandChain failed"); } private function eventChainFail(event:ChainEvent):void { trace("EventChain failed"); } } }
Below is my PersistenceController that will initialize the local database; its init function is called when the INIT_PERSISTENCE event is dispatched. When the database initialization is finished event.complete(); has to be called in order to proceed with chain execution:
package controllers { import flash.events.IEventDispatcher; import org.swizframework.utils.chain.EventChainStep; public class PersistenceController { [Dispatcher] public var dispatcher:IEventDispatcher; [Mediate("INIT_PERSISTENCE")] public function init(event:EventChainStep):void { trace("Initializing PersistenceController..."); event.complete(); } } }
This last snippet demonstrates the RemoteServiceDelegate class, which can be used to invoke remote services. It works with AsyncCommandChainStep:
package delegates { import mx.rpc.AsyncToken; import mx.rpc.remoting.RemoteObject; public class RemoteServiceDelegate { [Inject] public var remoteObject:RemoteObject; public function ping(param:String):AsyncToken { return remoteObject.ping(param); } } }
You can download my demo project source code from here; note that it doesn’t do anything except print out traces to the console. This zip contains a build of latest Swiz source code from GitHub that has some FunctionChainStep fixes.
Cooklet.com launched (Open Screen Project funded)
Very recently I was speaking at a press conference of a new culinary service called Cooklet.com. Okay, you may be wondering what my role at that event. So first of all, the Cooklet team is located out of Wroclaw/Poland, but this obviously isn’t the primary reason
What really brought me there is the fact that Cooklet is using a lot of Adobe technology, specifically our Platform technologies. Cooklet.com itself is a standard HTML based website but at the same time it has a desktop version that runs with Adobe AIR. There is also Cooklet Mobile built with Flash Lite and hosted as an application in the Nokia OVI store. Another very important fact is that this project was funded by the Open Screen Project initiative; you can find more details here as well a registration form to apply yourself.
The service itself has some unique and interesting features. What I really like is in-browser drag-and-drop capability that you can use to add new recipes to your cookbook or shopping list. The really cool thing here is that when you drag the recipe to the cooking list you instantly get access to it from your mobile phone. Another really cool thing is that the recipes get automatically translated into different languages. In the future this may give its users access to really tasty recipes from different cuisine.
Additionally the desktop version gives you offline access to your recipes that you may need in your kitchen. Also it has a great user experience and interactions that mimic reading real printed version of a cookbook.
Obviously Cooklet.com has much more interesting features and I encourage you to give it a try.
Check out the Cooklet Lite demo video below. Now I’m just waiting for the Cooklet team to provide an AIR for Mobile version that I can run on my Nexus One phone ;)
Flerry 1.2.0 released!
I’m proud to announce Flerry 1.2.0, which brings following new features and changes:
- Java discovery process has been completely rewritten. Now it looks into default location on given operating system:
- Windows – c:\Windows\System32\javaw.exe (starting from version 6 this is the default Java location)
- Mac – /usr/bin/java if that doesn’t exist it checks /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java
- Linux – /usr/bin/java if that doesn’t exist it checks /etc/alternatives/java
- In case any of these default locations fail it tries fallback mechanism, on Windows it is a native code compiled into FindJava.exe utility. This utility checks the registry on users machine and returns path to the location where java is installed. This was contributed by my colleague Serge Jespers; he used it for his Package Assistant Pro application. In case of Mac and Linux it uses native „/usr/bin/whereis java“ command to discover where Java is installed.
- The default location where to place jar files has been renamed to libs as it no longer contains only jar files. Now it also contains FindJava.exe utility. It can be customized by setting libsDirectory property on NativeObject class.
- Adding all jars under libsDirectory folder into the classpath automatically. Specifying it explicitly is no longer required.
- Compiled java code can be placed under classes folder. It is not required to package it into a jar anymore. This makes debugging and testing the application much easier.
- Out-of-the-box support for java code debugging. Flerry Getting Started (part 2) video tutorial covers how this can be used.
- Improved communication from AIR to Java, now it can support large objects transfer. This is due to object splitting into 256 bytes chunks.
- Added basic set of FlexUnit tests.
- Added Ant build script.
- Updated AMF serialization jars from BlazeDS 4.0.
- Removed reference between flerry and flerry-demo projects. Now flerry-demo is a standalone project referenced by flerry.swc.
This time kudos go to Jhonny Everson, Serge Jespers and Erko Bridee for their contributions and support.
Watch getting started video tutorials to get up to speed with Flerry.



