[Catalyst] Re: use for expand_modules

Gianni Ceccarelli dakkar at thenautilus.net
Mon Aug 8 09:13:14 GMT 2011

(re-sent, since apparently the mailing list didn't like my previous


I am using expand_modules at work. It may not be the best solution to
my problem, but it seemed appropriate. Let's see if I can describe
what I'm doing.

I have a thing that just happens to be a Catalyst application, using
Catalyst::Engine::Stomp to respond to ActiveMQ messages instead of
HTTP requests. Since the actual logic of the application does not
depend on the fact that we're using Catalyst as a module loader and
dispatcher, I have written a sort of "insulation layer" between
Catalyst and the actual business logic.

The "insulated" consumer modules look like this:

  package MyApp::Consume::Something;
  use Moose;
  extends 'MyFramework::Base::Consume';

  sub routes {
    return {
      a_queue_name => {
        a_message_type => \&a_method_to_handle_it,
        another_message_type => \&you_get_the_idea,
      a_different_queue => {
        and_so => \&on_and_on,

  # here go the actual subs / methods

The MyFramework::Base::Consume class is a Catalyst::Component (well,
better said, ->can('COMPONENT')), and implements a expand_modules
method that does more or less this:

- collect the queues this module wants to listen on
- create (via Moose::Meta::Class->create, and only if it's not already
  there) a Catalyst Controller per queue, under the appropriate
  namespace (the controller inherits from
  Catalyst::Controller::MessageDriven, part of the
  Catalyst::Engine::Stomp distribution)
- add a "after 'register_actions'" modifier on the controller to
  create the actions that will dispatch the message to the appropriate
  method as required


  sub expand_modules {
    my ($class) = @_;
    my @ret = ();
    for my $queue (keys %{$class->routes}) {
      my $controller_name = the_name_for($queue);
      if (not is_controller_there($controller_name)) {
      for my $message_type (keys %{$class->routes->{$queue}}) {
      push @ret, $controller_name;
    return @ret;

Answers to some probable questions:

- Can't your Consume modules be Controllers, and then you do
  $something to the Dispatcher?

  Maybe, but Catalyst::Engine::Stomp /
  Catalyst::Controller::MessageDriven do enough strange things to the
  dispatch, and I prefer not to rewrite them

- Do you really need to insulate your modules so much from Catalyst?

  There is talk to use some other system to handle ActiveMQ in the
  future, and I don't want to have to touch my code more than strictly

- How the &%$%$^# did you think this was a good idea?

  Well, it *is* documented :) And it seems to be the obvious hook:
  when loaded, my component creates more components…


- am I insane? :)

- is there a better / cleaner / more future-proof way of getting the
  same result?

- will the "much better solution" that t0m hinted at still allow me
  this kind of contortions?

Thanks :)

	Dakkar - <Mobilis in mobile>
	GPG public key fingerprint = A071 E618 DD2C 5901 9574
	                             6FE2 40EA 9883 7519 3F88
	                    key id = 0x75193F88

"Why's it called Ming?" said the Archchancellor, on cue.
The Bursar tapped the pot. It went *ming*.
        -- Discworld archeology revealed
           (Terry Pratchett, Moving Pictures)

More information about the Catalyst mailing list