Home > Flex, tutorial > Fabrication: PureMvc cleaned up.

Fabrication: PureMvc cleaned up.

January 27th, 2009

So when I last posted an article, I did an example on PureMvc. It was just something small and simple. One of the thing I do not like about PureMvc though (plan on writing an article about this later) is the mediators “handleNotification” function. It seems to almost be common practice with PureMvc that you have this function and it just turns into a massive switch statement to find out what came back, where it goes, how its handled, etc. Fine some something small, but we have all seen what can happen with rogue switch statements. I’m sure there are more eligant work arounds for this, but I see it as a decent sized flaw.

However, while talking to a friend at work about this, he mentioned a framework called Fabrication. And this seems to really handle all of these problems. Not only does it handle all of these problems, but it makes your mediator classes a LOT more crisp and clean. One of the key factors in this framework is the fact that it uses reflection in order to handle all of the notifications. No longer do you have to something like this

1
2
3
override public function listNotificationInterests():Array{
	return [PureMvcConstants.DATA_LOADED];
}

Instead there are two bits of functionality that it really takes advantage of, both utilizing reflection. The first bit is a reactTo. You can use this to react to specific events such as a button click or something like that. You dont even have to register a listener for this. Once your component is registered and the functions are set in place, its all hooked in for you.

The second bit is similar and is called a respondTo. This is used in order to respond to notifications that are sent out. It also takes advantage of reflection. So instead of having your handleNotifications function listening for everything and you have your switch statement of death, you are able to just setup a separate function for each notification.

So if yo have something like this:

1
sendNotification("setText");

Only thing you need set is this:

1
public function respondToSetText(note:INotification):void{}

Now in this example, I did cut out the use of a proxy and the need for a facade is “removed”. I say that with quotes because its still there, but (according to this documentation), it provides that for you. While I have provided these libraries in the source, you will need to make sure you have the following libraries:

So, now that I’ve talked about it enough, lets look at a simple example of both a reactTo and a respondTo.

Here is our main mxml file (FabricationExample.mxml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="utf-8"?>
<fab:FlexApplication
	xmlns:fab="org.puremvc.as3.multicore.utilities.fabrication.components.*"
	 xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
	<mx:Script>
		<![CDATA[
			import com.codeofdoom.command.FabricationExampleStartUpCommand;
			override public function getStartupCommand():Class{
				return FabricationExampleStartUpCommand;
			}
		]]>
	</mx:Script>
	<mx:VBox>
		<mx:Label id="reactToLabel"/>
		<mx:TextInput id="inputText" text="type something here"/>
		<mx:Button id="submitButton" label="Submit"/>
		<mx:Label id="respondToLabel"/>
	</mx:VBox>		
</fab:FlexApplication>

Now you are going to notice a few things that might stick out.
1.Instead of an mx:Applicaiton tag, there is a fab:FlexApplication tag. Guess where the facade is hiding?
2.You will also notice that this already this and override getStartupCommand. Something extremely important you must note though. You MUST, I repeat MUST follow the format of [MyApplicationName]StartupCommand. This is due to reflection that I was speaking about earlier.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.codeofdoom.command
{
	import com.codeofdoom.mediator.FabricationExampleMediator;
 
	import org.puremvc.as3.multicore.interfaces.INotification;
	import org.puremvc.as3.multicore.utilities.fabrication.patterns.command.SimpleFabricationCommand;
 
	public class FabricationExampleStartUpCommand extends SimpleFabricationCommand
	{
		override public function execute(notification:INotification):void{
			registerMediator(new FabricationExampleMediator(notification.getBody()));
		}
 
	}
}

I also wanted to make mention of the point of the StartupCommand. This is where you would register your mediators and proxies for your application. I failed to mention this in the last post, so I just wanted to clear that up.

So, we register our one mediator for this guy, which will (through the constructor) pass in our viewComponent.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.codeofdoom.mediator
{
	import flash.events.Event;
	import flash.events.MouseEvent;
 
	import mx.controls.Button;
 
	import org.puremvc.as3.multicore.interfaces.INotification;
	import org.puremvc.as3.multicore.utilities.fabrication.patterns.mediator.FlexMediator;
 
	public class FabricationExampleMediator extends FlexMediator
	{
		public static const NAME:String = "FabricationExampleMediator";
		public function FabricationExampleMediator(viewComponent:Object=null)
		{
			super(NAME, viewComponent);
		}
 
		override public function onRegister():void{
			super.onRegister();
		}
 
		public function reactToSubmitButtonClick(e:MouseEvent):void{
			fabricationExample.reactToLabel.text = fabricationExample.inputText.text;
			sendNotification("setText",new Date());
		}
 
		public function respondToSetText(note:INotification):void{
			fabricationExample.respondToLabel.text = "The reactTo was set at " +note.getBody();
		}
 
		public function get submitButton():Button{
			return  fabricationExample.submitButton as Button;
		}
 
		public function get fabricationExample():FabricationExample{
			return viewComponent as FabricationExample;
		}
	}
}

Next in the mediator, we have two get functions. One is for our viewComponent (FabricationExample in our case) and the other is for the submitButton. Now, I am going to go over this at the end, but the spelling and capitalization of these functions are important.

Aside from the two get functions, we have two others. The reactTo function and the respondTo function. Lets talk about these a little more in depth. These are both mapped through reflection. If you notice on the respondTo function, its called respondToSetText. The SetText the name of a notification. Thats all you need to do to let this mediator know that they are interested in that notification. Similarly, the reactTo is setup through reflection but a little bit different. Notice in our main mxml file we have a button called submitButton and here we have a reactToSubmitButtonClick. This is a direct mapping to that event.

Really that’s all that we need to setup. When you run the application, the reactTo on the button click gets called. It takes what we typed and drops it on the label above it. Right after we set it though, we send off the notification “setText” with the current date as the body. That gets picked up by the respondToSetText, which drops the body of that to the label below the button. That is really it. Your output should look something like this:

I’ll be honest, I do find PureMvc a bit more powerful that cairngorm, but I also found it a bit much to setup. Aside from that, the way that it handled notifications really turned me off. This however clears all that up. Not only that, but look at the mxml file again. Not ONE single bit of logic in there. All that is there are just the visual components. Nothing else but the getStartupCommand. Brings tears to my eyes :) .

Now all this amazingness does require use to be nice and folllow some rules,specifically for the reactTo methods. Luckily, they put the rules on their site. So here they are, cut/paste from the man himself(or herself? the team?)

1. To use Reactions you must declare you target component with a getter in the Mediator using CamelCasing. In the above example the submitButton getter referenced the submitButton child of the viewComponent.
2. In the reactTo method the submitButton must be upper CamelCased. In the above example submitButton became SubmitButton.
3. The Component’s event name must also be upper CamelCased. In the above example the click event became Click.
4. If you have any other code implemented in the onRegister method you need to call super.onRegister.
5. Similarly if you have any other code implemented in the onRemove method you need to call super.onRemove.

If you have the time, I do recommend you check out their wiki at least. They did a great job on posting some good and easy to follow documents on there. Also a few things that I didnt get to mention in this such as interceptors. Really worth a look.

Here is the source

Please feel free to comment

Marcel Flex, tutorial , , , , ,

  1. February 7th, 2009 at 11:00 | #1

    Hey Marcel,

    Thanks for taking the time to try Fabrication, much appreciated.

    peace,
    darshan

  2. cease
    February 9th, 2009 at 22:06 | #2

    Hi good writeup . Question – on the wiki it says

    override public function getClassByName(path:String):Class {
    return getDefinitionByName(path) as Class;
    }

    must be defined somewhere. I don’t see it anywhere in your example. is it not needed anymore ?

  3. admin
    February 9th, 2009 at 23:01 | #3

    Thanks for taking the time out to read the article. You do pose a good question though. I see in the wiki where it says that. However, looking at the wiki, it does say “when using modular applications”. I am not sure if this means you are loading flex modules by chance.

    Digging into the source, I noticed it said this within IFabrication.as

    “It allows the Fabrication apparatus to use reflection inside a module application swf from the parent shell swf.”

    My guess is that this refers to the situations of if you have similarly named components within your module that you load into your parent application. I know with cairngorm, we had to make sure the we did not run into conflicts with similarly named event names, and we used the fully qualified pathnames. My GUESS is that this would be the same thing. I am just guessing though.

    Hope that helps.

  4. cease
    February 10th, 2009 at 13:24 | #4

    hey thanks for the reply , yeah actually that helps out a lot.

  5. November 19th, 2009 at 10:10 | #5

    Just an FYI – but CamelCase, or upper CamelCase is not camelCase. In camelCase the first letter is lower case – always. Making the first letter upper case is called PascalCase.

  6. lilblacky
    January 15th, 2010 at 10:44 | #6

    Thanks for this it’s been helpful. I’m missing one thing with fabrication.. how do I registerCommands at the facade level?

  1. February 7th, 2009 at 10:56 | #1