Gianni Ceccarelli


CatalystX::ConsumesJMS - role for components providing Catalyst actions consuming messages


version 1.08


  package MyApp::Base::MyConsumer;
  use Moose;
  extends 'Catalyst::Component';
  with 'CatalystX::ConsumesJMS';

  sub _kind_name {'MyConsumer'}
  sub _wrap_code {
    my ($self,$c,$destination_name,$msg_type,$route) = @_;
    my $code = $route->{code};
    my $extra_config = $route->{extra_config};
    return sub {
      my ($controller,$ctx) = @_;
      my $message = $ctx->req->data;


  package MyApp::MyConsumer::One;
  use Moose;
  extends 'MyApp::Base::MyConsumer';

  sub routes {
    return {
      my_input_destination => {
        my_message_type => {
          code => \&my_consume_method,
          extra_config => $whatever,

  sub my_consume_method {
    my ($self,$message) = @_;

    # do something

Also, remember to tell Catalyst to load your MyConsumer components:

   search_extra [ ::MyConsumer ]


This role is to be used to define base classes for your Catalyst-based JMS / STOMP consumer applications. It's not to be consumed directly by application components. See CatalystX::RouteMaster for implementation details and a rationale. Most of the rest of this document is copied from there.


Subclasses of your component base specify which messages they are interested in, by writing a routes sub, see the synopsis for an example.

They can specify as many destinations and message types as they want / need, and they can re-use the code values as many times as needed.

The main limitation is that you can't have two components using the exact same destination / type pair (even if they derive from different base classes!). If you do, the results are undefined.

It is possible to alter the destination name via configuration, like:

    my_input_destination the_actual_destination_name

You can also do this:

    my_input_destination the_actual_destination_name
    my_input_destination another_destination_name

to get the consumer to consume from two different destinations without altering the code.

You can even alter the message type via the configuration:

    <my_input_destination the_actual_destination_name>
      my_message_type actual_type_1
    <my_input_destination another_destination_name>
      my_message_type actual_type_2
      my_message_type actual_type_3

That would install 3 identical actions for the following destination / message type pairs:

actual_type_1 on the_actual_destination_name
actual_type_2 on another_destination_name
actual_type_3 on another_destination_name

The "code"

The hashref specified by each destination / type pair will be passed to the "_wrap_code" function (that the consuming class has to provide), and the coderef returned will be installed as the action to invoke when a message of that type is received from that destination.

Required methods


As in the synopsis, this should return a string that, in the names of the classes deriving from the consuming class, separates the "application name" from the "component name".

These names are mostly used to access the configuration.


This method is called with:

  • the Catalyst application as passed to register_actions

  • the destination name

  • the message type

  • the value from the routes corresponding to the destination name and message type slot (see "Routing" above)

You can do whatever you need in this method, but the synopsis gives a generally useful idea. You can find more examples of use at

The coderef returned will be invoked as a Catalyst action for each received message, which means it will get:

  • the controller instance (you should rarely need this)

  • the Catalyst application context

You can get the de-serialized message by calling $c->req->data. The JMS headers will most probably be in $c->req->env (or $c->engine->env for older Catalyst), all keys namespaced by prefixing them with jms.. So to get all JMS headers you could do:

   my $psgi_env = $c->req->can('env')
                  ? $c->req->env
                  : $c->engine->env;
   my %headers = map { s/^jms\.//r, $psgi_env->{$_} }
                 grep { /^jms\./ } keys $psgi_env;

You can set the message to serialise in the response by setting $c->stash->{message}, and the headers by calling $c->res->header (yes, incoming and outgoing data are handled asymmetrically. Sorry.)


List (not arrayref!) of class names that the controllers generated by _generate_controller_package should inherit from. Defaults to 'Catalyst::Controller::JMS'.


List (not arrayref!) of role names that should be applied to the controllers created by _generate_controller_package. Defaults to the empty list.


  my %extra_params = $self->_action_extra_params(

You can override this method to provide additional arguments for the create_action call inside _generate_register_action_modifier. For example you could return:

  attributes => { MySpecialAttr => [ 'foo' ] }

to set that attribute for all generated actions. Defaults to:

  attributes => { 'MessageTarget' => [$message_type] }

to get Catalyst::Controller::JMS to create an action to which that message type gets dispatched.


Gianni Ceccarelli <>


This software is copyright (c) 2012 by

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.