RSS
 

Understanding PureMVC Pipes

15 Jun

Disclaimer: This a bit of a longer post!!

The pipes utility is newer to PureMVC and as such, I’ve seen questions on the blogosphere regarding it’s use.

The plumbing metaphor should help wrap you head around this utility and it’s use. Keep in mind that a pipe allows for one-way message flow.

So let’s take a look at how the utility can be used.

One great features of ‘Pipes’ is that they can use used on top of an existing app. That is, you’ll simply need to define a JunctionMediator at/for each integration point.

Let’s look at the simplest case, an application that loads and communicates with a module. We’ll assume that at some point you’ll want to use this same app to use multiple modules down the road. You’ll need to create a JunctionMediator for the application and a JunctionMediator for the module. We’ll dive into the details for those mediators but at a high level, that’s it – we simply define a ‘JunctionMediator’ for each ‘player.’

Here’s a simple diagram

Simple Pipe

Our JunctionMediator’s will be connected together with pipes. We’ll have one pipe that allows for application-to-module message flows and another pipe that allows for module-to-application flows.

On the receiving end of a pipe, we’ll want a pipe listener (you’ll have only one pipe listener for a given pipe). We’ll use pipe listeners to handle incoming pipe messages.

To send messages down a pipeline, we’ll normally use the Junction’s ‘sendMessage’ function.

Back to our simple example, our app’s JunctionMediator would be responsible for creating the app’s pipe fittings, creating pipes to connect to those fittings to the module.

So the first thing our app’s JunctionMediator would do would be to create a new junction at creation.


public class ApplicationJunctionMediator extends JunctionMediator
{
public function ApplicationJunctionMediator()
{
super(NAME, new Junction());
}

Once this mediator is registered with our facade, we’d want to create the PipeFittings. We’ll use a TeeSplit for outgoing and TeeMerge for incoming. The TeeSplit will allow us to connect to multiple modules for outbound messages. The TeeMerge will allow multiple modules to send messages up to our main app. We’ll also want to add a pipe listener on our TeeMerge. This listener will allow us to handle the messages being sent up from the modules to the app.


override public function onRegister():void
{
junction.registerPipe( PipeAwareModule.APP_TO_MODULE_PIPE, Junction.OUTPUT, new TeeSplit() );
junction.registerPipe( PipeAwareModule.MODULE_TO_APP_PIPE, Junction.INPUT, new TeeMerge() );
junction.addPipeListener( PipeAwareModule.MODULE_TO_APP_PIPE, this, handlePipeMessage );
}

Our handlePipeMessage function is responsible for handling the messages coming up from our modules to our app.


function handlePipeMessage(message:IPipeMessage):void

Being a Mediator, we can define what application-level notifications we’re interested in and how to handle those notifications. That is, we’ll want to utilize listNotificationInterests() and handleNotification(note:INotification). We’ll use these to listen for notifications and turn desired notifications into messages to pass down our pipes.

For example, our Mortgage App would listens for request for loan notifications and turn those notifications into messages.


override public function handleNotification(note:INotification):void
{

switch( note.getName() )
{
case MortgageAppEventNames.REQUEST_FOR_LOAN:
var loanMessage:Message = new Message(MortgageAppEventNames.REQUEST_FOR_LOAN,null,note);
junction.sendMessage(PipeAwareModule.APP_TO_MODULE_PIPE,loanMessage);
break;
}
}

Our application JunctionMediator will also typically listen for a notification that a module has been loaded. Our app’s JunctionMediator will then create new pipes to connect the app’s junctionMediator to the modules junctionMediator. Something along the lines of…


override public function handleNotification(note:INotification):void
{

switch( note.getName() )
{
case MortgageAppEventNames.REQUEST_FOR_LOAN:
var loanMessage:Message = new Message(MortgageAppEventNames.REQUEST_FOR_LOAN,null,note);
junction.sendMessage(PipeAwareModule.APP_TO_MODULE_PIPE,loanMessage);
break;

case ModuleEvents.CONNECT_MODULE_JUNCTION:
var module:IPipeAwareModule = note.getBody() as IPipeAwareModule;

// Create the pipe
var moduleToApp:Pipe = new Pipe();
// Connect the pipe to our module
module.acceptOutputPipe(PipeAwareModule.MODULE_TO_APP_PIPE, moduleToApp);

// Connect the pipe to our app
var appIn:TeeMerge = junction.retrievePipe(PipeAwareModule.MODULE_TO_APP_PIPE) as TeeMerge;
appIn.connectInput(moduleToApp);

// Create the pipe
var appToModule:Pipe = new Pipe();
// Connect the pip to our module
module.acceptInputPipe(PipeAwareModule.APP_TO_MODULE_PIPE,appToModule);

// Connect the pipe to our app
var appOut:TeeSplit = junction.retrievePipe(PipeAwareModule.APP_TO_MODULE_PIPE) as TeeSplit;
appOut.connect(appToModule);

break;

// And let super handle the rest (ACCEPT_OUTPUT_PIPE, ACCEPT_INPUT_PIPE, SEND_TO_LOG)
default:
super.handleNotification(note);

}
}

Finally our application’s JunctionMediator will handle the incoming pipe messages.


override public function handlePipeMessage(message:IPipeMessage):void
{
// Handle our Module->Application integration
trace(message);
var note:INotification = message.getBody() as INotification;

switch(note.getName())
{
case MortgageAppEventNames.LOAN_QUOTE_READY:
sendNotification(note.getName(),note.getBody(),note.getType());
break;
default:
sendNotification(note.getName(),note.getBody(),note.getType());
break;
}
}

That covers the basic responsibilities for our app’s JunctionMediator.

Our module’s JunctionMediator would listen for messages coming in on the APP_TO_MODULE named pipe and send [outbound] messages on the MODULE_TO_APP pipe.


override public function handleNotification(note:INotification):void
{
// Handle our Module->Application integration
switch( note.getName() )
{
case ModuleFacade.QUOTE_GENERATED:
// convert our *local* notification into the application format
var quoteMessage:Message = new Message(MortgageAppEventNames.LOAN_QUOTE_READY,null,
new Notification(MortgageAppEventNames.LOAN_QUOTE_READY,note.getBody(),note.getType()));
junction.sendMessage(PipeAwareModule.MODULE_TO_APP_PIPE,quoteMessage);
break;
}
}

override public function handlePipeMessage( message:IPipeMessage ):void
{
// Handle our Application->Module integration
var note:INotification = message.getBody() as INotification;
switch(note.getName())
{
case MortgageAppEventNames.REQUEST_FOR_LOAN:
sendNotification(ModuleFacade.QUOTE_REQUESTED,note.getBody(),note.getType());
break;
}

}

If the app was to load another module our diagram would become…
Pipes App with Two Modules

If your still have questions – just ask 🙂

 
 

Leave a Reply

 

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Anti-spam image

 
  1. Joel

    June 16, 2008 at 9:54 pm

    Nice. Thanks for taking the time to put this together. I’ve been building my latest project using the multicore PMVC, not because I need module support now, but because I don’t see any good reason NOT to use the MC version. Now down the road I can drop in a module, fix up the plumbing, and it is off to the races.

     
  2. Mike

    June 16, 2008 at 11:38 pm

    The puremvc pipes demo is great … but it’s too difficult to really understand…. I wanted to know if you could create a simple/basic pipes demo of your own? I really learned a lot from your modular Mortgage demo… could you maybe port that for use with pipes??

     
  3. Joshua

    June 17, 2008 at 7:28 am

    Joel agreed – I don’t see much benefit in *NOT* using the MultiCore version.

    Mike, I’ve already ported the mortgage app demo to pipes – it was my ‘hello world’ into the pipes world. I’ll see if I can get around to posting it here today or tomorrow.

     
  4. WS-Blog » A basic PureMVC MultiCore AS3 example using Pipes Utility and Modules

    June 21, 2008 at 1:12 pm

    […] “Understanding PureMVC Pipes” by Joshua Ostrom. Great tutorial! […]

     
  5. mani

    July 16, 2008 at 10:13 pm

    Thank you very much~~~
    But why I don’t fond the modules file in the source file?
    import com.dl.modules.pipes.interfaces.IPipeAwareModule;
    import com.dl.modules.pipes.components.PipeAwareModule;

    Please help~~

     
  6. amahi

    July 18, 2008 at 9:26 am

    Thanks for the explanation.
    Something I don’t understand: Do we need a Junction per module or can we create one alone junction for all the module?

     
  7. Joshua

    July 18, 2008 at 4:36 pm

    Amahi,
    You’d want a junction at each module. Junction is where you’ll connect your pipes ‘together.’ A typical setup would include a junction for your ‘shell’ app and junction for each loaded module.

    The junctions are connected together via pipes.

    The unction is the ‘integration’ point for your app / module into the pipe architecture.

     
  8. mani

    July 22, 2008 at 6:48 am

    hello, Joshua, thanks you very much~

    But I have a question about the source of the demo, could you opensource the lib of that?

    Thanks for your time ^_^
    mani.

     
  9. manis

    July 23, 2008 at 3:21 am

    Could you openSource the lib of the demo?
    Thanks~~

     
  10. Y.Boy

    August 6, 2008 at 10:25 pm

    Hi, thanks for this..

    May you provide a example?

     
  11. Joshua

    August 7, 2008 at 11:28 am

    Y.Boy,
    As soon as some time frees up, I’ll post some more examples and see if I can post the lib as well.

    Josh

     
  12. diamondTearz

    September 20, 2008 at 2:38 pm

    Josh,
    Thank you so much for this explicit walkthrough. This was exactly what I needed right now to clear up some of the foggy patches in my understanding of the framework.

     
  13. Russ

    March 2, 2009 at 10:44 pm

    Josh,
    I wonder if you have any thoughts on using pipes and loading swfs made in Flash in to the main Flex app rather than Flex modules? I have tried it out, making my movies main implement the IPipeAware interface, and creating junction mediator for it. It seems to works ok, but I feel there is something missing.

     
  14. Joshua

    March 4, 2009 at 8:51 am

    Russ,
    Sure, there’s no ‘flex’ requirement for dynamic modules. If you dig back a bit further I posted on AS3 only dynamic modules – http://www.joshuaostrom.com/2008/05/24/as3-puremvc-dynamic-modules/ which might help you move forward, although it sounds like your well on your way! 🙂

     
  15. Sebastian

    March 10, 2009 at 5:42 am

    Hello and thanks a lot for this post!

    One simple question though, the best place to put the ApplicationJunctionMediator.as is in the “top level” package of my app or modules, right?

    Cheers

     
  16. Scottae

    September 18, 2009 at 1:37 pm

    I’m sorry if my question has been addressed before, but why bother using the pipes utility? All the examples I’ve seen are fairly complex for something as simple as making a module talk to it’s shell. It seems that you could do something as simple as have each side listen for a custom event….viola, done. I just don’t see the benefit of setting up all the pipes stuff.

     
  17. Joshua

    September 22, 2009 at 7:13 am

    Scottae,
    It’s common to have your modules implement an interface and communicate via that contract. There’s not wrong with that at all.

    Pipes benefit is realized when you’re working with a PureMVC app. You simply send your [PureMVC] notification and your done, your message is routed to it’s destination. That destination may be in the same module, or down/up a module, up/down multiple modules, etc.

    Hope that helps.

    Josh

     
  18. Ashok

    December 26, 2009 at 12:51 pm

    Thanks guys,

    I have started using Pipes in a largest application we have started recently. This tutorial helped me to in a great way.

    Ashok

     
  19. Sander

    January 8, 2010 at 1:09 pm

    Thanks a lot. A very useful article.

     
  20. Name

    March 15, 2010 at 4:46 pm

    Thank you for your time! =^_^=