Mediator can't hear an Event
Hi,
I've put together a small RL project for learning purposes and
have come upon a strange road block. Here's what's happening:
I have a context that triggers the StartupCommand through
ContextEvent.STARTUP. Check.
The StartupCommand has the getTemplatesService load a dummy
service. Check.
When done, the service dispatches a TemplateResultEvent.RECEIVED
event with a templates:ArrayCollection payload. Check.
Through a commandMap in the context I have mapped the
TemplateResultEvent.RECEIVED event to
HandleReceivedTemplatesCommand
HandleReceivedTemplatesCommand runs and updates the templateModel.
Check
The TemplateModel's setter triggers the
TemplateModelEvent.TEMPLATES_UPDATED event which fires. Check.
In the onRegister function of the SpecsViewMediator, the mediator
listens for the TemplateModelEvent.TEMPLATES_UPDATED and has the
updateTemplatesDD handler waiting to handle that event.
Problem!
The updateTemplatesDD handler never runs.
I tried debugging it, but get nothing useful (probably because the Robotlegs swcs are compiled). Before I use the uncompiled Robotlegs for debugging, can anyone see anything that I'm omitting, or point out the not so obvious?
Thanks,
Tim
Code:
//CONTEXT
public class TemplateMakerContext extends Context
{
public function TemplateMakerContext(contextView:DisplayObjectContainer = null, autoStartup:Boolean = true)
{
super(contextView, autoStartup);
}
override public function startup():void
{
injector.mapSingleton(TemplateModel);
injector.mapSingleton(GetTemplatesService);
mediatorMap.mapView(SpecsView, SpecsViewMediator);
commandMap.mapEvent(TemplateResultEvent.RECEIVED, HandleReceivedTemplatesCommand, TemplateResultEvent);
commandMap.mapEvent(ContextEvent.STARTUP, StartupCommand);
// startup
dispatchEvent(new ContextEvent(ContextEvent.STARTUP));
super.startup();
}
}
//STARTUP COMMAND
public class StartupCommand extends Command
{
[Inject] public var getTemplatesService:GetTemplatesService;
override public function execute():void
{
getTemplatesService.load();
}
}
//SERVICE
public class GetTemplatesService extends Actor
{
public function load():void
{
//stub for now
onResult([{name:"template_a", id:1}, {name:"template_b", id:2}]);
}
private function onResult(results:Array):void
{
var e:TemplateResultEvent = new TemplateResultEvent(TemplateResultEvent.RECEIVED);
e.results = new ArrayCollection(results);
dispatch(e);
}
}
//COMMAND
public class HandleReceivedTemplatesCommand extends Command
{
[Inject] public var templateModel:TemplateModel;
[Inject] public var templateResultEvent:TemplateResultEvent;
override public function execute():void
{
//update model
templateModel.templates = templateResultEvent.results;
}
}
//MODEL
public class TemplateModel extends Actor
{
protected var _templates:ArrayCollection;
public function get templates():ArrayCollection;
{
return _templates;
}
public function set templates(value:ArrayCollection):void
{
_templates = value;
var e:TemplateModelEvent = new TemplateModelEvent(TemplateModelEvent.TEMPLATES_UPDATED);
e.templates = _templates;
dispatch(e);
}
}
//MEDIATOR
public class SpecsViewMediator extends Mediator
{
[Inject]
public var specsView:SpecsView;
[Inject]
public var templateModel:TemplateModel;
override public function onRegister():void
{
eventMap.mapListener(eventDispatcher, TemplateModelEvent.TEMPLATES_UPDATED, updateTemplatesDD, TemplateModelEvent);
}
public function updateTemplatesDD(event:TemplateResultEvent):void
{
specsView.template_brand_dd.dataProvider = event.results;
trace('updated')
}
}
//VIEW
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
x="10" y="10" width="250" height="768" backgroundColor="#525252" title="Template View">
<s:DropDownList id="template_brand_dd" x="10" y="18" width="228" />
</s:Panel>
//EVENT
public class TemplateModelEvent extends Event
{
public static const TEMPLATES_UPDATED:String = "templates_updated";
public function TemplateModelEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false)
{
super(type, bubbles, cancelable);
}
protected var _templates:ArrayCollection;
override public function clone():Event
{
return new TemplateModelEvent(type, bubbles, cancelable);
}
public function get templates():ArrayCollection
{
return _templates;
}
public function set templates(value:ArrayCollection):void
{
_templates = value;
}
}
- src.zip 6.27 KB
Showing page 2 out of 2. View the first page
Comments are currently closed for this discussion. You can start a new one.
Keyboard shortcuts
Generic
? | Show this help |
---|---|
ESC | Blurs the current field |
Comment Form
r | Focus the comment reply box |
---|---|
^ + ↩ | Submit the comment |
You can use Command ⌘
instead of Control ^
on Mac
Support Staff 31 Posted by Ondina D.F. on 29 Jul, 2011 07:49 AM
Oh, that’s great, Tim! I’ll take a look at it and get back to you later today.
Ondina
Support Staff 32 Posted by Ondina D.F. on 29 Jul, 2011 05:05 PM
That was a lot of work, Tim!! And you were fast!
I'm no UML expert either :) I know it’s not easy to make such a sequence diagram.
I thought it would be more suited to show the 3 major areas/regions/scopes of an RL-Flex application:
RobotlegsInternals as a framework ( Context, MediatorMap, MediatorBase - of interest to us in our example)
RobotlegsImplementation (ApplicationContext, Commands, Models, Services and Mediators)
FlexComponents (View: ContextView- Application and a SomeView- child component)
If you think that another type of diagram would be easier to use, or would be more clear, I’d be the last one to complain about it :) Or if you have another tool, that would facilitate the visual representation, go on and use it. Our goal isn’t to present UML best practices, is it?
I’m not sure which name would be self-explanatory for the 3 areas. RL-Internal, RL-Implementation, Flex-Components... or flex what?
Let’s say we’ll agree upon a better naming later on, but for now I think it’s important to know, if having only 3 sequence instances/areas/bounderies would be better than having an instance for every class dispatching an event.
Exactly, none would benefit from too many details. And we really should try to keep the focus on RL + Flex only.
I’ll use your diagram to see how it could be simplified and I’ll think about an easier way to represent the flow, while keeping the instances in 3 groups. I will keep you posted about any progress or new ideas, but it will happen slowly. I’m very sorry about that, but
hopefully my slow steps won’t be a problem for you.
Thank you for your work and ideas :)
Ondina
33 Posted by Timur on 29 Jul, 2011 06:57 PM
Hi Ondina,
I agree, I have mixed feelings about UML in general, some of it could be useful, some of it less intuitive. I'm wondering whether a sequence diagram serves this purpose well, or whether it might be better to break this diagram into more manageable chunks, perhaps of different type. I think sequence diagrams start to reach a point of diminishing return once they exceed a certain level of detail. The challenge it seems is to show the three areas you outlined above in a clear manner, while illustrating sequence of Flex framework events, RobotlegsImplementation/Project custom events, and RobotlegsInternals events.
I think that works. Flex-Component is closely related to Flex-Application, since Flex-Application extends a Flex-Component and adds additional functionality. So it could be Flex-Component/Application.
Do you mean reduce the number of detail?
I look forward to it. Speed is not a requirement here, only clarity is.
Thank you for taking the time and creating several illustrative projects that started it all.
Tim
Support Staff 34 Posted by Ondina D.F. on 30 Jul, 2011 09:49 AM
Tim,
You are so right! Sequence Diagram is definitively not suited to our needs, or simply because we are no-uml-experts ;) And yes, it might be better to break this diagram into more manageable chunks.
Ok, then I’ll go with FlexComponents (Application and ChildComponent) , RobotlegsInternal, RobotlegsImplementation
Yep. Less details, more clarity :)
I’m starting now with a diagram by using only the traces related to the ContextView.
Till then...
Ondina
Support Staff 35 Posted by Ondina D.F. on 31 Jul, 2011 11:13 AM
Update:
It's cold and rainy outside, so I spent some time playing with diagrams ;)
RLStartupSequence_01.png was the first one I made, then RLStartupSequence_02.png and the last one is RLContextViewFlow_01.png
None of them is complete or nice or clear enough. I also didn’t check if the flow is absolutely correct. I also misused the Sequence Diagram’s elements and so on. Anyway I wanted to let you see them, so you can better understand what I was talking about, when I mentioned the 3 areas of interest. I used Swimlanes(FlexComponents, RLInternal,RLImplementation) and Lifelines(ContextView, ApplicationContext etc)
RLContextViewFlow_01 shows only the flow for the ContextView + ApplicationMediator + service call. I think we should have more than one diagram. One for the ContextView, one for SomeView and one with both ContextView and SomeView flows, with fewer details than in the first ones. Then we could have variations of the combined flow for the different scenarios (service call on startupcomplete, on applicationcomplete, from onregister of the mediator...) if we want to.
After taking a closer look at the trace statements, I saw that their order of execution isn’t correct in my code. For example I put trace("[MediatorMap] createMediatorUsing() "+viewComponent+ " "+mediator); in createMediatorUsing after it calls registerMediator(), so registerMediator appears first. I’m sorry for that. My excuse: I made changes to the code in kind of a hurry, between different other tasks and formulating an answer for our discussion.
So Tim, I hope my ugly diagrams are at least illustrating my point. I’ll try to see if I can reduce the number of details even more without loosing valuable information.
Ondina
36 Posted by Timur on 01 Aug, 2011 12:19 AM
Hi Ondina,
I think the Swimlanes idea is brilliant. I'm poring over the ContextView Flow now. I like how you have color coded different areas and have assigned different shapes to events, etc. Here are my thoughts/questions/suggestions:
Do you think it would make sense to somehow differentiate the ContextEvent.STARTUP chevron visually? I'm thinking that the other events are triggered by either Flex Components or by RL Internals, whereas ContextEvent.STARTUP is a rather arbitrary event and could be confused in this diagram for a "system" level event.
Would it be slightly less confusing, do you think, to lower the ContextEvent.STARTUP chevron so that it would not be parallel (on the same Lifeline) with the mapInjections in the rightmost swimlane? I don't think they are related, but being parallel in the diagram makes you associate them. I've attached a small mockup of what I mean.
Another question I have is related to the MapView.registerMediator()->MediatorBase.preRegister()->MediatorBase.onRegister() where ApplicationMediator.onRegister()->super() would call the same MediatorBase.onRegister(). It's not yet clear to me how this works since visually the linear continuity is interrupted.
Should we show the SomeModelEvent.DATA_UPDATED chevron for completeness' sake, or do you think it's unnecessary?
In my version of Startup_Takethree project, I have MapViewsCommand dispatch ContextEvent.STARTUP_COMPLETE that really does nothing. It is the onApplicationComplete handler that triggers the SomeServiceRequest. I mention this because you have a commented out line of code:
//commandMap.mapEvent(ContextEvent.STARTUP, SomeServiceRequestCommand, ContextEvent, true); //won't work
And I'm wondering whether we are showing a flow that won't work.
That's all I can think of for now on the ContextView Flow. Thanks again, Ondina, for doing an excellent job of it. I will now look over the other two diagrams.
Tim
Support Staff 37 Posted by Ondina D.F. on 01 Aug, 2011 01:32 PM
Hi Tim,
I’ll open a new thread under [Examples], because I think that our current discussion is a little outside the scope of this thread. Your initial question has been answered.
Our goal now is to find the best way to explain the start-up process in a Flex-RL application through:
code
diagrams
explanations
I wasn’t sure where to put it. What category does it belong to? It’s not a solution yet, it’s not a problem or question, so I decided to put it under [Examples], because we will have one sooner or later. I also don’t know what would be the most descriptive title for the new thread. I’ll name it “Tracking the Start-up Process of a Flex-RL application” for now. I can change it later into something better(your suggestion?).
http://knowledge.robotlegs.org/discussions/examples/12-tracking-the...
See you there :)
Ondina
Ondina D.F. closed this discussion on 01 Nov, 2011 11:37 AM.