That dreaded .......Error: Injector is missing a rule to handle injection into target [object MainMediator]. Target dependency: btn_del_activity

Peter O'Connell's Avatar

Peter O'Connell

03 Mar, 2011 02:43 AM

Hi all,
I'm new to RL and this is driving me crazy. I've written a couple of RL apps before but I've never seen this happen..

I have a man app / view with buttons on it.
If I try and add a MediatorMap.Mapview statement for a button the app works fine.
If I try and add a MediatorMap.Mapview statement for a 2nd button i get the Injector is missing a rule for the first button.
Am I missing something silly here ? I hope I am !

Here is my MainContext

package
{

import flash.display.DisplayObjectContainer;
import org.robotlegs.mvcs.Context;

public class MainContext extends Context
{

    public function MainContext()
    {
        super();
    }

    override public function startup():void
    {
        // Controller

        // Model
        injector.mapSingleton(svc_get_templateList);
        // Services

        // View

        mediatorMap.mapView(btn_del_activity, MainMediator);
        mediatorMap.mapView(btn_new_activity, MainMediator);            

        // Startup complete
        super.startup();
    }

}

}

Here is my mediator

package
{

import org.robotlegs.mvcs.Mediator;
import flash.filesystem.*;
import flash.net.*;
import flash.data.*;

public class MainMediator extends Mediator
{

    [Inject] public var b1:btn_del_activity;

    public function MainMediator()
    {
    }

    override public function onRegister():void
    {

        b1.label = "test";
    }

}

}

Here is the button mxml component that I used as well

<?xml version="1.0" encoding="utf-8"?>
<mx:Button xmlns:fx="http://ns.adobe.com/mxml/2009"

      xmlns:s="library://ns.adobe.com/flex/spark"
      xmlns:mx="library://ns.adobe.com/flex/mx"     >
<fx:Script> 
    <![CDATA[

        import mx.collections.ArrayCollection;
        import mx.controls.Alert;

    ]]> 
</fx:Script>
<fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>

</mx:Button>

I've scaled my app back to the above simple code to troubleshoot but i still cannot figure it out.
If someone has any insight into this error I would love to know what I have done wrong.
My air app uses the 1.30 robotlegs framework swc.
Thx in advance,
Peter

  1. 1 Posted by Michal Wroblews... on 03 Mar, 2011 08:54 AM

    Michal Wroblewski's Avatar

    As I can see you have the same mediator mapped to 2 different view classes. You should use 2 separated mediators (extend button base component to 2 different mediators one per view class). If you really need to have the same mediator your button class has to implement interface.

    Add that line to your main component tag:
    implements="IMyButton"

    In mediator class use:
    [Inject] public var b1:IMyButton;

    and in you app context use:

    mediatorMap.mapView(btn_del_activity, MainMediator,IMyButton) mediatorMap.mapView(btn_new_activity, MainMediator,IMyButton)

  2. 2 Posted by Peter O'Connell on 03 Mar, 2011 09:45 AM

    Peter O&#x27;Connell's Avatar

    ok, I quickly added a new mediator for the second button, mapped it to the new mediator, and that has fixed it - Thankyou ! but I dont understand why ?
    I'm looking at an older app that I wrote a few weeks back and it has all the view objects mapped into 1 BIG mediator. Not saying that its correct to do it that way, but it worked. I dont know what has changed but I havnt used the interface method that you suggested.
    Very strange.
    Can anyone explain the logic as to why I need to use separate mediators for separate view components. Wouldnt it be alright to group certain view components into the 1 mediator for convenience ?
    Appreciate any insight / feedback.
    Peter

  3. 3 Posted by Stray on 03 Mar, 2011 10:06 AM

    Stray's Avatar

    Hi Peter,

    it looks to me like you're mapping an object? The first param in mapView is usually a Class or Fully Qualified Class Name. Unless that's an IDE library class?

    Generally, no, it's not advised to group several views together into one mediator. (Though you can mediate a parent view).

    Obviously, from a good-OO-design point of view, there's a general preference for well-defined classes with single responsibilities. Generally it's better to use polymorphism than switches to determine specific paths through code.

    If you have a mediator that requires several [Inject] points to be filled in, you run into race conditions and technical difficulties because the mediator might be created at a point where only one of the classes required for injection exists.

    The robotlegs mediator map is designed to help your app stay flexible - the mediatorMap waits for the view to be on the stage, so used conventionally you're free to change the timing of adding your views without having to think about the impact on the mediator creation process. But if you have multiple injection points (of views) into your mediator then you lose this.

    I can understand that it seems like (and often is) overkill to mediate buttons individually. Rather than mediate several different things through injections like that, I'd prefer to mediate the parent view and expose the required actions through as3signals - so I'd have a 'deleteRequested' signal and a 'saveRequested' signal (or similar) and then just wire the mediator to those signals rather than the click of the buttons.

    If you're not familiar with signals then alternatively you could expose the buttons with a getter on the parent view. Technically this breaks the 'Law of Demeter' - you're directly working with objects through another object - but I think that's a better, easier to understand, less likely to create 'WTF?' moments, approach when compared with trying to use the multiple-injection approach.

    I hope this makes some sense - I have *no* idea how your approach worked previously, except that possibly if you'd mapped each one to the same mediator, and then your first view landed on the stage, the mediator map would - by chance largely - probably know how to fulfil the other injections. But I think it's a side-effect rather than intended functionality - Till might be able to clarify that. I'd certainly be interested to see the code.

    Stray

  4. Support Staff 4 Posted by Till Schneidere... on 03 Mar, 2011 10:22 AM

    Till Schneidereit's Avatar

    I fully agree to what Stray said, just wanted to follow up on the
    previously working "big mediator" approach.
    I don't think that the exact scenario you outlined in your first post
    ever worked. There's just no way the injector would ever have known
    how to fulfill the other injections, be it by chance or otherwise.

    Correct me if I'm wrong, but might the difference between your current
    approach and what you did in that older project be that back then you
    used `injector.mapValue` to map the views? That way, the injector
    would have lasting knowledge of how to fulfill these dependencies.

    If that's not the case, you'd have to post some boiled-down version of
    your older app for us to investigate further. If you want us to, that
    is: Same as Stray I'd heavily recommend against the "big mediator"
    approach.

  5. 5 Posted by Peter O'Connell on 03 Mar, 2011 10:29 AM

    Peter O&#x27;Connell's Avatar

    The first param in my mapview is a mxml button that i created. So i was trying to mediate 2 separate button objects into the same mediator. I was just reading some more RL documentation and I think my logic was incorrect. I was trying to achieve most of my logic in one big mediator. i.e just map all view components (buttons, textboxes etc) into the mediator and handle all logic in their. Now from my reading I should have (and as Michal also advised) create separate mediators for each view component and use events to communicate between them. I think I was being lazy and trying to avoid using too many events. Does this sound correct ? I need to keep reminding myself - events events events ! I'm not familiar with signals (have no idea actually - one thing at a time).
    Thanks Stray for your input too - I think I understand most of what you said - apart from the signals bit.
    Yes I cannot think how the older app worked now...its designed very similar to this one...a main form with controls that all get injected into 1 mediator... anyhow I'm not too worried about that now. I think I am happy to proceed on the right path now with my separate mediators and events events events.....
    btw - you guys rock - its fantastic the feedback you give here.
    Peter

  6. Support Staff 6 Posted by Till Schneidere... on 03 Mar, 2011 10:36 AM

    Till Schneidereit's Avatar

    Glad we could help!

    Now on the topic of "achieving logic in the mediator": Stray has an
    excellent post on her blog about how you shouldn't misuse your
    mediators as controllers:
    http://www.xxcoder.net/my-mailman-doesnt-open-my-mail

  7. 7 Posted by Michal Wroblews... on 03 Mar, 2011 10:40 AM

    Michal Wroblewski's Avatar

    And yes, one big mediator would be a better idea. There would be no necessary new mediators for each new button (and buttons dont have to have their own classes). You can create mediator for container class which contains your buttons. Then the container is mediated (injected in your mediator) and you access buttons like this: container.btn1. If your container is contextView check this url: http://knowledge.robotlegs.org/kb/reference-mvcs-implementation/can...

  8. 8 Posted by krasimir on 03 Mar, 2011 11:41 AM

    krasimir's Avatar

    Hi all,

    Off topic: I found that a lot of people are trying to use the framework for everything in their applications. Isn't it better to use RL as a backbone. I.e. if we have a login form (two text fields and a button) isn't it better to crate a view LoginFormView and mediator LoginFormMediator. And leave the actions about the fields (like checks) and the button in the view's logic (which is not part of the RL directly). I think that there is no need to create a mediator for every button or the text field. What you think ?

  9. 9 Posted by Michal Wroblews... on 03 Mar, 2011 11:44 AM

    Michal Wroblewski's Avatar

    Yep, that's how it should be done. View should be a standalone transferable fully-working component. Mediator just connects it to the framework wherever it's added

  10. Stray closed this discussion on 03 Apr, 2011 11:11 AM.

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