(re-sent, since apparently the mailing list didn't like my previous attempt)
Hello. 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 Pseudo-code: 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)) { create_controller($controller_name,$queue); } for my $message_type (keys %{$class->routes->{$queue}}) { add_after_register_actions( $controller_name, $message_type, $class->routes->{$queue}{$message_type} ); } 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 necessary - 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… Questions: - 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) _______________________________________________ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/