Thinking in Java And Flex

Michael Niu’s Technical Weblog

Mate-Tag Base Framework

Mate will become another hot pot in Flex area . It use configuration to call the service and handle the event. It also uses configuration to update the Bindable object. Somehow The Mate is The “springframework” in Flex Area.

There are two architecture level diagrams of Mate. One is from Yakov Fain of Farata Systems, Another is from Mate funder company ASFusion. I like the later one:

Lets use mate to develop the buddyList application

1.Create the core component of mate —-EventMap.

The EventMap is the heart of mate it glues all the other component and control the process:

BuddyListEventMap.mxml:

<?xml version=”1.0″ encoding=”utf-8″?>

 

<EventMap

 

xmlns=”http://mate.asfusion.com/

xmlns:mx=http://www.adobe.com/2006/mxml>

</EventMap>

 

 

I will add the related code later. Now we need tell the main app that initialize the EventMap:

Flex_Mate.mxml:

<?xml version=”1.0″ encoding=”utf-8″?>

 

<mx:Application

 

xmlns:map=”com.ny.flex.mate.map.*” xmlns:views=”com.ny.flex.mate.views.*” xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute>

<mx:Script>

<![CDATA[

[

 

Bindable

]

 

public var

viewStackSelectedIndex :int = 0;

]]>

 

</mx:Script>

<map:BuddyListEventMap/>

 

 

<mx:HBox horizontalAlign=”center” verticalAlign=”top” width=”100%” height=”100%” y=”0” x=”0>

 

 

<mx:ViewStack id=”viewStack” resizeToContent=”true” selectedIndex=”{viewStackSelectedIndex}>

 

 

<views:LoginView />

 

 

<views:BuddyListView/>

 

 

</mx:ViewStack>

 

 

</mx:HBox>

</mx:Application>

 

 

2. Create the LoginView :

<?xml version=”1.0″ encoding=”utf-8″?>

 

<mx:Panel

 

xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute” width=”300” height=”200” horizontalAlign=”center” verticalAlign=”middle” title=”Flex Cirngorm Login>

 

<mx:Script>

<![CDATA[

 

import

com.ny.flex.mate.event.LoginEvent; 

 

import

com.ny.flex.mate.vo.User; 

 

import

mx.validators.Validator; 

 

private function login():void

{ 

 

if

(Validator.validateAll(validators).length == 0){ 

 

var loginUser:User = new

User();

loginUser.userName=username.text;

loginUser.password=password.text;

 

var loginEvent:LoginEvent = new

LoginEvent(LoginEvent.LOGIN);

loginEvent.loginUser = loginUser;

dispatchEvent(loginEvent);

}

}

]]>

 

</mx:Script>

 

<!– Validators–>

 

 

<mx:Array id=”validators>

 

 

<mx:StringValidator id=”userNameValidator” source=”{username}” property=”text” required=”true/>

 

 

<mx:StringValidator id=”passwordValidator” source=”{password}” property=”text” required=”true/>

 

 

</mx:Array>

 

 

<mx:Form

 

id=”loginForm” x=”0” y=”0>

 

 

<mx:FormItem label=”Username:>

 

 

<mx:TextInput id=”username/>

 

 

</mx:FormItem>

 

 

<mx:FormItem label=”Password:>

 

 

<mx:TextInput id=”password” displayAsPassword=”true/>

 

 

</mx:FormItem>

 

 

<mx:FormItem direction=”horizontal” verticalGap=”15” paddingTop=”5” width=”170>

 

 

<mx:Button id=”loginBtn” label=”Login” click=”login()”/>

 

 

</mx:FormItem>

 

 

</mx:Form>

</mx:Panel>

 

 

See the action method above the LoginEvent is dispatched. Now create the LoginEvent:

 

package

 

import

com.ny.flex.mate.vo.User;

 

import

flash.events.Event;

 

public class LoginEvent extends

Event

{

 

public static const LOGIN:String = “login”

; 

 

public var

loginUser:User; 

 

public function LoginEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false

)

{

 

super

(type, bubbles, cancelable);

}

}

}

 

com.ny.flex.mate.event

{

 

The “bubbles” has to be “true”, it makes EventMap can handle it. The magic of mate comes in the EventMap . The LoginEvent can handle by tag :

…..

 

<EventHandlers type=”{LoginEvent.LOGIN}>

 

 

<RemoteObjectInvoker destination=”flexmvcRO” method=”authenticate

arguments=”{event.loginUser}>

 

 

<resultHandlers>

 

 

<MethodInvoker generator=”{LoginService}

method=”onResult_Authenticate

arguments=”{resultObject}/>

 

 

</resultHandlers>

 

 

</RemoteObjectInvoker>

 

 

</EventHandlers>

……

 

In the EvevntHandler , You can define the service call function(RemoteObjectInvoker here) . and It also define the result handler specify the service class ,method and arguments.

Lets see the LoginService object:

package

 

com.ny.flex.mate.service

{

 

import

com.ny.flex.mate.vo.User;

 

public class

LoginService

{

[

 

Bindable

] 

 

public var

authUserName:String; 

[

 

Bindable

] 

 

public var

viewStackSelectedIndex:int ;

 

public function onResult_Authenticate(user:User):void

{

authUserName = user.userName;

viewStackSelectedIndex = 1;

}

}

}

 

 

 

 

The service class handle the result and make the return object bindable. now we need update target views. Another shine point of mate is Injecting the bindable object to the target view! you just need add another tag in EventMap class . (This is damn cool):

 

<Injectors target=”{BuddyListView}>

 

 

<PropertyInjector targetKey=”authUserName” source=”{LoginService}

sourceKey=”authUserName/>

 

 

</Injectors>

 

<Injectors target=”{Flex_Mate}>

 

 

<PropertyInjector targetKey=”viewStackSelectedIndex” source=”{LoginService}

sourceKey=”viewStackSelectedIndex/>

 

 

</Injectors>

 

 

 

You just need specify the target view, taget key , source service object and source key!

Finally lets define the target view :BuddyListView:

<?xml version=”1.0″ encoding=”utf-8″?>

 

<mx:Panel

 

xmlns:mx=”http://www.adobe.com/2006/mxml” title=”Buddy List of {authUserName} creationComplete=”getBuddyList()” width=”500” height=”320>

<mx:Script>

<![CDATA[

 

import

mx.collections.ArrayCollection; 

 

import

com.ny.flex.mate.event.GetBuddyListEvent; 

[

 

Bindable

] 

 

public var

authUserName:String; 

[

 

Bindable

] 

 

public var

buddyCollection:ArrayCollection;

 

private function getBuddyList():void

{ 

 

var getBuddyListEvent:GetBuddyListEvent = new

GetBuddyListEvent(GetBuddyListEvent.GET_BUDDY_LIST);

getBuddyListEvent.authUserName = authUserName;

dispatchEvent(getBuddyListEvent);

}

]]>

 

</mx:Script>

 

<mx:DataGrid id=”buddyList” dataProvider=”{buddyCollection}” borderStyle=”none” width=”100%” height=”100%>

 

 

<mx:columns>

 

 

<mx:DataGridColumn dataField=”firstName” headerText=”First Name/>

 

 

<mx:DataGridColumn dataField=”lastName” headerText=”Last Name/>

 

 

</mx:columns>

 

</mx:DataGrid>

</mx:Panel>

 

Checkout the “{autherUsername}”, it comes from the LoginService.

You probably wonder about “buddyListCollection”. It means another around development:

Action–>Dispatch Event–>Config Handler–>create service–>Inject Bindable Object –>another Action….

All the other code is blow:

GetBuddyListEvent.as:

 

package

 

import

flash.events.Event;

 

public class GetBuddyListEvent extends

Event

{

 

public static const GET_BUDDY_LIST =“getAllFriends”

; 

 

public var

authUserName:String;

 

public function GetBuddyListEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false

)

{

 

super

(type, bubbles, cancelable);

}

}

}

 

com.ny.flex.mate.event

{

 

BuddyService.as:

 

package

 

import

mx.collections.ArrayCollection;

 

public class

BuddyService

{

[

 

Bindable

] 

 

public var

buddyList:ArrayCollection; 

 

public function

onResult_GetBuddyList(buddies:ArrayCollection){

buddyList = buddies;

}

}

}

 

com.ny.flex.mate.service

{

 

The completely EventMap file: BuddyListEventMap.mxml

<?xml version=”1.0″ encoding=”utf-8″?>

 

<EventMap

 

xmlns=”http://mate.asfusion.com/” xmlns:mx=”http://www.adobe.com/2006/mxml>

 

<mx:Script>

<![CDATA[

 

import

com.ny.flex.mate.event.BDbbdEvent; 

 

import

com.ny.flex.mate.service.BuddyService; 

 

import

com.ny.flex.mate.event.GetBuddyListEvent; 

 

import

com.ny.flex.mate.views.BuddyListView; 

 

import

com.ny.flex.mate.service.LoginService; 

 

import

com.ny.flex.mate.event.LoginEvent;

]]>

 

</mx:Script>

 

 

<EventHandlers type=”{LoginEvent.LOGIN}>

 

 

<RemoteObjectInvoker destination=”flexmvcRO” method=”authenticate” arguments=”{event.loginUser}>

 

 

<resultHandlers>

 

 

<MethodInvoker generator=”{LoginService}” method=”onResult_Authenticate” arguments=”{resultObject}/>

 

 

</resultHandlers>

 

 

</RemoteObjectInvoker>

 

 

</EventHandlers>

 

 

<EventHandlers type=”{GetBuddyListEvent.GET_BUDDY_LIST}>

 

 

<RemoteObjectInvoker destination=”flexmvcRO” method=”{GetBuddyListEvent.GET_BUDDY_LIST}” arguments=”{event.authUserName}>

 

 

<resultHandlers>

 

 

<MethodInvoker generator=”{BuddyService}” method=”onResult_GetBuddyList” arguments=”{resultObject}/>

 

 

</resultHandlers>

 

 

</RemoteObjectInvoker>

 

 

</EventHandlers>

 

<Injectors target=”{BuddyListView}>

 

 

<PropertyInjector targetKey=”authUserName” source=”{LoginService}” sourceKey=”authUserName/>

 

 

<PropertyInjector targetKey=”buddyCollection” source=”{BuddyService}” sourceKey=”buddyList/>

 

 

</Injectors>

 

<Injectors target=”{Flex_Mate}>

 

 

<PropertyInjector targetKey=”viewStackSelectedIndex” source=”{LoginService}” sourceKey=”viewStackSelectedIndex/>

 

 

</Injectors>

</EventMap>

 

 

Summary

I discussed  flex development  in  last 5 blogs. What is  the best choice  ?

I think  the central management  will be  NO1. choice for the small project. Because  you dont need   learn any  new framework  and  you still  get clear architecture .

For the  mate and Cairngorm,   Mate seems  win the conpetition  now. Because

For Cairngorm:

1.   Cairngorm  is too complicate  and  study cost is higher.

2.  Cairngorm has some Junk code for my  opionion, ie.frontcontrollerI.

For  Mate,

1 . It is  simpler than  Cairngorm, and easier to study.

2. You get benefit from  EventMap, Because  you dont need  write ther glue code between  event and the  service.

3.You get pain from EventMap.  Just imagine  you have  50 actions and 100 objects to bind. you have to put  lots of   configration  stuff in your EventMap, Then EventMap become the disastor!

So  if you have to use  cairngorm   use  my solution  Cairngorm without FrontContoller.

For the mate,   if they can add  the Meta Tag instead of  the EventMap. i.e.:

[EventHadler ={name ="myHandler", serviceclass="myservice" result , taget ...}]

MateDispatch(myevent).

So  you dont need   config anything,  I am waiting for  this.

 

 

 

 

July 29, 2008 - Posted by Niu Yong | Flex | | No Comments Yet

No comments yet.

Leave a comment