A few days ago Powerflasher released a new version of their logging tool SOS. I have used it in the past but stopped using it because I switched to Mac. Since the new version also runs on OS X I gave the new version a try and it works nicely.
I have posted a little extension for SOS about two years ago and now I made a little update which is easier to use. It works the same way as the TraceTarget I already blogged about.
Download the SOSTargetLib.swc and put it into your libs directory.
In you Flex project simply put this line into you main MXML:
<logging:SOSTarget fieldSeparator="->" includeCategory="true" includeTime="true" includeLevel="true" />And add the namespace: xmlns:logging=”com.soenkerohde.logging.*”
The rest works like described in my post about TraceTarget.
This version also supports multiline logs which can show up collapsed and can be expanded:

The application code for the example above:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()" xmlns:logging="com.soenkerohde.logging.*"> <mx:Script> <![CDATA[ import mx.logging.Log; import mx.logging.ILogger; private static const logger:ILogger = Log.getLogger("Main"); private function init():void { logger.debug("debug"); logger.info("info"); logger.warn("warn"); logger.error("error"); logger.fatal("fatal"); logger.info("This is a multiline log example\nwith a second line."); } ]]> </mx:Script> <logging:SOSTarget fieldSeparator="->" includeCategory="true" includeTime="true" includeLevel="true" /> </mx:Application>
There were a lot of news and posts about Flex and open-source so I thought it would be nice to summarize it.
Grant Skinner has posted a wonderful summary about common source code licenses.
Matt Chotin asked for feedback on suggested projects related to Flex. Personally I would love to see an ORM framework like suggested by Christophe Coenraets which works with BlazeDS.
Alistair McLeod and Steven Webster blogged about the move of Cairngorm from the Adobe Labs wiki to Adobe Open Source.
I just received the Adobe Edge Newsletter which covers an article about the art of open-source license by Dave McAllister.
Here a list of some client side open source software I use the most to develop Flex/AIR:
Here a list of Flex frameworks (InfoQ Flex Framework article):
and IoC frameworks:
and component libraries:
and animation/UI frameworks:
and 3D engines:
And much more if you check out OSFlash or search Google Code for “flex” or “as3″.
And for the server-side there is not less. Adobe recently proposed AMF support for the Zend framework and of course BlazeDS which fits wonderfull into a stack with Spring and Hibernate!
This is an example I have in the pipe for a long time but I think it still might be helpful to post it.
I had the use case to build a Flex UI where elements are visible/invisible depending on the user who is logged in. The combination of the properties includeInLayout and visible does the trick.
includeInLayout docs:
“Specifies whether this component is included in the layout of the parent container. If
true, the object is included in its parent container’s layout. Iffalse, the object is positioned by its parent container as per its layout rules, but it is ignored for the purpose of computing the position of the next child.”
So when for instance a Button has includeInLayout and visible set to false the control is hidden and does not effect the layout and is not accessible. Now how can we bind this to the roles of a user who is logged into the application?
I thought of this:
<Button label="delete" includeInLayout="{user.hasRole(UserRole.DELETE)}" visible="{user.hasRole(UserRole.DELETE)}" />The User class:
package { import flash.events.Event; import flash.events.EventDispatcher; public class User extends EventDispatcher { private static const ROLES_CHANGED:String = "rolesChanged"; [Bindable] public var username:String; public var password:String; private var _roles:Array; public function get roles():Array { return _roles; } public function set roles(a:Array):void { _roles = a; dispatchEvent(new Event(ROLES_CHANGED)); } public function User(username:String = "", password:String = "") { this.username = username; this.password = password; } [Bindable(event=ROLES_CHANGED)] public function hasRole(userRole:UserRole):Boolean { if(roles != null) { for each(var role:UserRole in roles) { if(role.equals(userRole)) { return true; } } return false; } return false; } } }
The key is the hasRole method which is bindable and can be used for MXML bindings to the includeInLayout and visible property. All bindings will refresh every time the roles setter is called as the ROLES_CHANGED event is dispatched within. And this event is the custom binding event for the hasRole method.
The UserRole class:
package { public class UserRole { public static const DO_A:UserRole = new UserRole("DO_A"); public static const DO_B:UserRole = new UserRole("DO_B"); public static const DO_C:UserRole = new UserRole("DO_C"); public static const VIEW_A:UserRole = new UserRole("VIEW_A"); public static const VIEW_B:UserRole = new UserRole("VIEW_B"); public static const VIEW_C:UserRole = new UserRole("VIEW_C"); private var name:String; public function UserRole(name:String) { this.name = name; } public function equals(userRole:UserRole):Boolean { if(userRole != null) { return this.name == userRole.name; } return false; } } }
The UserRole class specifies all available Roles as constants so they can be passed as parameters to the hasRole method of the User class.
I build a little example application which you can try here and view the source here.
Within a Flex application it is a very common thing to show lists of items or domain objects for instance a list of articles, users or whatever.
There are many ways to implement this and I would like to share an approach which I call Lazy Model Responder. I am using the Cairngorm microarchitecture where I implement the ModelLocator, BusinessDelegate and ServiceLocator.
The ModelLocator provides a reference to my Lazy Model Responder instance which uses the BusinessDelegate which relies on the ServiceLocator.
package mypackage { import flash.events.Event; import flash.events.EventDispatcher; import mx.collections.IList; import mx.logging.ILogger; import mx.logging.Log; import mx.rpc.IResponder; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; public class LazyModelResponder extends EventDispatcher implements IResponder { private static const logger:ILogger = Log.getLogger("LazyModelResponder"); private static const ITEMS_LOADED:String = "itemsLoaded"; private var _items:IList; private var _pending:Boolean = false; [Bindable(event=ITEMS_LOADED)] public function get items():IList { if(_items == null) { loadItems(); } return _items; } private function loadItems():void { if(!_pending) { logger.info("load items"); pending = true; // MyDelegate expectes an IResponder in the // constructor to add it to the AsyncToken new MyDelegate(this).loadItems(); } } public function result(data:Object):void { _pending = false; var re:ResultEvent = data as ResultEvent; _items = IList(re.result); logger.debug("items loaded. count: ", _items.length) dispatchEvent(new Event(ITEMS_LOADED)); } public function fault(info:Object):void { _pending = false; var fe:FaultEvent = info as FaultEvent; logger.error("loading failed ", fe.message); } } }
The class implements the IResponder interface (methods result and fault) and a getter where a view can bind against:
[Bindable(event="itemsLoaded"] public function get items():IList;
The Data Binding within the view is always updating when the itemsLoaded event is fired within the class.
The view could look like this
<mx:List dataProvider="{MyModelLocator.getInstance().myModelResponder.items}" />When the view comes into the display chain the data binding is invoked which calls the items getter. There is no setter as this is read-only.
This calls loadItems which loads the data over the delegate and sets pending to true to be called only once. “Null” is returned when items getter is called the first time which is fine for the view as it shows nothing but triggered the backend call with its existence / data binding.
Depending on the success of the call the fault or result method is called which sets pending back to false. If the call was successfully the data is stored in the result method and the itemsLoaded event is fire. This triggers the refresh of the data binding. The items getter is called again but this time the _items are not null so the list is returned which lets the data show up in the list view.
The view can of course also be a DataGrid or any other view which can render a list or in this case implements the IList interface.
Another possibility would be to not use the ModelLocator but setting the data binding outside of the view which would simplify unit testing for instance.







