package Catalyst::Controller::JMS;
{
$Catalyst::Controller::JMS::VERSION = '1.0';
}
{
$Catalyst::Controller::JMS::DIST = 'Catalyst-ActionRole-JMS';
}
use Moose;
use namespace::autoclean;
# ABSTRACT: controller base class to simplify usage of Catalyst::ActionRole::JMS
BEGIN { extends 'Catalyst::Controller::ActionRole' }
__PACKAGE__->config(
stash_key => 'message',
default => 'application/json',
map => {
'application/json' => 'JSON',
'text/x-json' => 'JSON',
},
);
around create_action => sub {
my ($orig, $self, %args) = @_;
return $self->$orig(%args)
if $args{name} =~ /^_(DISPATCH|BEGIN|AUTO|ACTION|END)$/;
my $type = delete $args{attributes}->{MessageTarget};
if ($type) {
$args{attributes}->{Path} = [$self->path_prefix()];
$args{attributes}->{JMSType} = [$type->[0] // $args{name}];
$args{attributes}->{Does} = [ 'Catalyst::ActionRole::JMS' ];
}
return $self->$orig(%args);
};
sub begin :ActionClass('Deserialize') { }
sub end :ActionClass('Serialize') {
my ($self,$c) = @_;
$c->stash->{message} = [$c->stash->{message}]
unless ref($c->stash->{message});
}
__PACKAGE__->meta->make_immutable;
1;
__END__
=pod
=encoding utf-8
=head1 NAME
Catalyst::Controller::JMS - controller base class to simplify usage of Catalyst::ActionRole::JMS
=head1 VERSION
version 1.0
=head1 SYNOPSIS
package MyApp::Controller::Something;
use Moose;
BEGIN { extends 'Catalyst::Controller::JMS' }
__PACKAGE__->config(
namespace => 'queue/my_queue',
);
sub my_message_type :MessageTarget {
my ($self,$c) = @_;
my $body = $c->req->data;
my $headers = $c->req->headers;
# do something
$c->res->header('X-Reply-Address' => 'temporary-queue-name');
$c->stash->{message} = { some => [ 'reply', 'message' ] };
return;
}
=head1 DESCRIPTION
This controller base class makes it easy to handle JMS-style messages
in your Catalyst application. It handles deserialisation and
serialisation transparently (thanks to
L<Catalyst::Action::Deserialize> and L<Catalyst::Action::Serialize>)
and sets up the attributes needed by L<Catalyst::ActionRole::JMS>. It
also sets up some sensible default configuration.
=head1 CONFIGURATION
__PACKAGE__->config(
stash_key => 'message',
default => 'application/json',
map => {
'application/json' => 'JSON',
'text/x-json' => 'JSON',
},
);
See L<Catalyst::Action::Deserialize> and
L<Catalyst::Action::Serialize> for what this means.
=head1 ACTIONS
=head2 Your actions
If you set the C<MessageTarget> attribute on an action, it will be
marked for dispatch based on the JMSType of incoming messages. More
precisely:
sub my_message_type :MessageTarget { }
is equivalent to:
sub my_message_type : Does('Catalyst::ActionRole::JMS')
JMSType('my_message_type')
{ }
And:
sub my_action :MessageTarget('my_type') { }
is equivalent to:
sub my_action : Does('Catalyst::ActionRole::JMS')
JMSType('my_type')
{ }
If you want to have a C<default> action to catch requests not matching
any other action, you have to declare it as:
sub default :Default { }
otherwise dispatch may not work properly, see
http://lists.scsys.co.uk/pipermail/catalyst/2012-March/028261.html for
some attempts at an explanation
=head2 C<begin>
De-serialises the body of the request into C<< $ctx->req->data >>. See
L<Catalyst::Action::Deserialize> for details.
=head2 C<end>
Serialises C<< $ctx->stash->{message} >> into the response body. See
L<Catalyst::Action::Serialize> for details.
B<NOTE>: if C<< $ctx->stash->{message} >> is not a reference, it will
be wrapped in an arrayref. Some L<Catalyst::Action::Serialize> plugins
don't like serialising plain scalars.
=head1 EXAMPLES
You can find examples of use in the tests, or at
https://github.com/dakkar/CatalystX-StompSampleApps
=head1 AUTHOR
Gianni Ceccarelli <gianni.ceccarelli@net-a-porter.com>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2011 by Net-a-porter.com.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut