Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

transformer instance, validation, & docs

  • Loading branch information...
commit 6fe104e9c85a7d1f950c73ade3ab56ae763d2a48 1 parent 1e19674
Gianni Ceccarelli authored March 08, 2012
111  lib/Net/Stomp/Producer.pm
@@ -4,6 +4,7 @@ use namespace::autoclean;
4 4
 with 'Net::Stomp::MooseHelpers::CanConnect';
5 5
 use MooseX::Types::Moose qw(CodeRef HashRef);
6 6
 use Net::Stomp::Producer::Exceptions;
  7
+use Class::Load 'load_class';
7 8
 use Try::Tiny;
8 9
 
9 10
 # ABSTRACT: helper object to send messages via Net::Stomp
@@ -46,6 +47,77 @@ Or even:
46 47
 
47 48
 They all send the same message.
48 49
 
  50
+=head1 DESCRIPTION
  51
+
  52
+This class sends messages via a STOMP connection (see
  53
+L<Net::Stomp::MooseHelpers::CanConnect>). It provides facilities for
  54
+serialisation and validation.
  55
+
  56
+You can use it at several levels:
  57
+
  58
+=head2 Raw sending
  59
+
  60
+  my $p = Net::Stomp::Producer->new({
  61
+    servers => [ { hostname => 'localhost', port => 61613 } ],
  62
+  });
  63
+
  64
+  $p->send($destination,\%headers,$body_byte_string);
  65
+
  66
+This will just wrap the parameters in a L<Net::Stomp::Frame> and send
  67
+it. C<$destination> can be undef, if you have set it in the
  68
+C<%headers>.
  69
+
  70
+=head2 Serialisation support
  71
+
  72
+  my $p = Net::Stomp::Producer->new({
  73
+    servers => [ { hostname => 'localhost', port => 61613 } ],
  74
+    serializer => sub { encode_json($_[0]) },
  75
+  });
  76
+
  77
+  $p->send($destination,\%headers,$body_hashref);
  78
+
  79
+The body will be passed through the C<serializer>, and the resulting
  80
+string will be used as above.
  81
+
  82
+=head2 Transformer instance
  83
+
  84
+  $p->transform_and_send($transformer_obj,@args);
  85
+
  86
+This will call C<< $transformer_obj->transform(@args) >>. That
  87
+function should return a list (with an even number of elements). Each
  88
+pair of elements is interpreted as C<< \%headers, $body_ref >> and
  89
+passed to L</send> as above (with no C<destination>, so the
  90
+transformer should set it in the headers). It's not an error for the
  91
+transformer to return an empty list: it just means that nothing will
  92
+be sent.
  93
+
  94
+=head2 Transformer class
  95
+
  96
+  my $p = Net::Stomp::Producer->new({
  97
+    servers => [ { hostname => 'localhost', port => 61613 } ],
  98
+    transformer_args => { some => 'param' },
  99
+  });
  100
+
  101
+  $p->transform_and_send($transformer_class,@args);
  102
+
  103
+The transformer will be instantiated like C<<
  104
+$transformer_class->new($p->transformer_args) >>, then the object will
  105
+be called as above.
  106
+
  107
+=head2 Transform & validate
  108
+
  109
+If the transformer class / object supports the C<validate> method, it
  110
+will be called before sending each message, like:
  111
+
  112
+  $transformer_obj->validate(\%headers,$body_ref);
  113
+
  114
+This method is expected to return a true value if the message is
  115
+valid, and throw a meaningful exception if it is not. The exception
  116
+will be wrapped in a L<Net::Stomp::Producer::Exceptions::Invalid>. If
  117
+the C<validate> method returns false without throwing any exception,
  118
+L<Net::Stomp::Producer::Exceptions::Invalid> will still be throw, but
  119
+the C<previous_exception> slot will be undef.
  120
+
49 121
 =cut
50 122
 
51 123
 # we automatically send the C<connect> frame
@@ -68,6 +140,7 @@ sub _no_serializer {
68 140
 
69 141
     Net::Stomp::Producer::Exceptions::CantSerialize->throw({
70 142
         previous_exception => q{can't send a reference without a serializer},
  143
+        message_body => $message,
71 144
     });
72 145
 }
73 146
 
@@ -82,7 +155,11 @@ sub send {
82 155
     use bytes;
83 156
 
84 157
     try { $body = $self->serializer->($body) }
85  
-    catch { Net::Stomp::Producer::Exceptions::CantSerialize->throw };
  158
+    catch {
  159
+        Net::Stomp::Producer::Exceptions::CantSerialize->throw({
  160
+            message_body => $body,
  161
+        });
  162
+    };
86 163
 
87 164
     my %actual_headers=(
88 165
         %{$self->default_headers},
@@ -109,12 +186,22 @@ has transformer_args => (
109 186
     default => sub { { } },
110 187
 );
111 188
 
  189
+sub make_transformer {
  190
+    my ($self,$transformer) = @_;
  191
+
  192
+    return $transformer if ref($transformer);
  193
+
  194
+    load_class($transformer);
  195
+    if ($transformer->can('new')) {
  196
+        return $transformer->new($self->transformer_args);
  197
+    }
  198
+    return $transformer;
  199
+}
  200
+
112 201
 sub transform_and_send {
113 202
     my ($self,$transformer,@input) = @_;
114 203
 
115  
-    if (!ref($transformer) && $transformer->can('new')) {
116  
-        $transformer = $transformer->new($self->transformer_args);
117  
-    }
  204
+    $transformer=$self->make_transformer($transformer);
118 205
 
119 206
     my $method = try { $transformer->can('transform') }
120 207
         or Net::Stomp::Producer::Exceptions::BadTransformer->throw({
@@ -123,7 +210,23 @@ sub transform_and_send {
123 210
 
124 211
     my @messages = $transformer->$method(@input);
125 212
 
  213
+    my $vmethod = try { $transformer->can('validate') };
  214
+
126 215
     while (my ($headers, $body) = splice @messages, 0, 2) {
  216
+        if ($vmethod) {
  217
+            my $exception;
  218
+            my $valid = try {
  219
+                $transformer->$vmethod($headers,$body);
  220
+            } catch { $exception = $_ };
  221
+            if (!$valid) {
  222
+                Net::Stomp::Producer::Exceptions::Invalid->throw({
  223
+                    transformer => $transformer,
  224
+                    message_body => $body,
  225
+                    message_headers => $headers,
  226
+                    previous_exception => $exception,
  227
+                });
  228
+            }
  229
+        }
127 230
         $self->send(undef,$headers,$body);
128 231
     }
129 232
 
136  lib/Net/Stomp/Producer/Exceptions.pm
... ...
@@ -1,63 +1,85 @@
1 1
 package Net::Stomp::Producer::Exceptions;
2 2
 use Net::Stomp::MooseHelpers::Exceptions;
3 3
 
4  
-{package Net::Stomp::Producer::Exceptions::StackTrace;
5  
- use Moose::Role;
6  
- use namespace::autoclean;
7  
- with 'StackTrace::Auto';
8  
-
9  
- around _build_stack_trace_args => sub {
10  
-     my ($orig,$self) = @_;
11  
-
12  
-     my $ret = $self->$orig();
13  
-     push @$ret, (
14  
-         no_refs => 1,
15  
-         respect_overload => 1,
16  
-         message => '',
17  
-         indent => 1,
18  
-     );
19  
-
20  
-     return $ret;
21  
- };
22  
-}
23  
-
24  
-{package Net::Stomp::Producer::Exceptions::BadMessage;
25  
- use Moose;with 'Throwable',
26  
-     'Net::Stomp::MooseHelpers::Exceptions::Stringy',
27  
-     'Net::Stomp::Producer::Exceptions::StackTrace';
28  
- use namespace::autoclean;
29  
- use Data::Dump 'dump';
30  
- has message => ( is => 'ro', required => 1 );
31  
- has reason => ( is => 'ro', default => q{sending the message didn't work} );
32  
-
33  
- sub as_string {
34  
-     my ($self) = @_;
35  
-     sprintf "%s (%s): %s\n%s",
36  
-         $self->reason,dump($self->message),$self->previous_exception,
37  
-         $self->stack_trace->as_string;
38  
- }
39  
- __PACKAGE__->meta->make_immutable(inline_constructor=>0);
40  
-}
41  
-
42  
-{package Net::Stomp::Producer::Exceptions::CantSerialize;
43  
- use Moose;extends 'Net::Stomp::Producer::Exceptions::BadMessage';
44  
- has '+reason' => ( default => q{couldn't serialize message} );
45  
- __PACKAGE__->meta->make_immutable(inline_constructor=>0);
46  
-}
47  
-
48  
-{package Net::Stomp::Producer::Exceptions::BadTransformer;
49  
- use Moose;with 'Throwable',
50  
-     'Net::Stomp::MooseHelpers::Exceptions::Stringy',
51  
-     'Net::Stomp::Producer::Exceptions::StackTrace';
52  
- use namespace::autoclean;
53  
- has transformer => ( is => 'ro', required => 1 );
54  
-
55  
- sub as_string {
56  
-     my ($self) = @_;
57  
-     sprintf qq{%s is not a valid transformer, it doesn't have a "transform" method\n%s},
58  
-         $self->transformer,$self->stack_trace->as_string;
59  
- }
60  
- __PACKAGE__->meta->make_immutable(inline_constructor=>0);
  4
+{
  5
+package Net::Stomp::Producer::Exceptions::StackTrace;
  6
+use Moose::Role;
  7
+use namespace::autoclean;
  8
+with 'StackTrace::Auto';
  9
+
  10
+around _build_stack_trace_args => sub {
  11
+    my ($orig,$self) = @_;
  12
+
  13
+    my $ret = $self->$orig();
  14
+    push @$ret, (
  15
+        no_refs => 1,
  16
+        respect_overload => 1,
  17
+        message => '',
  18
+        indent => 1,
  19
+    );
  20
+
  21
+    return $ret;
  22
+};
  23
+}
  24
+
  25
+{
  26
+package Net::Stomp::Producer::Exceptions::BadMessage;
  27
+use Moose;with 'Throwable',
  28
+    'Net::Stomp::MooseHelpers::Exceptions::Stringy',
  29
+    'Net::Stomp::Producer::Exceptions::StackTrace';
  30
+use namespace::autoclean;
  31
+use Data::Dump 'dump';
  32
+has message_body => ( is => 'ro', required => 1 );
  33
+has message_headers => ( is => 'ro', required => 0 );
  34
+has reason => ( is => 'ro', default => q{sending the message didn't work} );
  35
+
  36
+sub as_string {
  37
+    my ($self) = @_;
  38
+    sprintf "%s (%s): %s\n%s",
  39
+        $self->reason,dump($self->message_body),
  40
+        $self->previous_exception,
  41
+        $self->stack_trace->as_string;
  42
+}
  43
+__PACKAGE__->meta->make_immutable(inline_constructor=>0);
  44
+}
  45
+
  46
+{
  47
+package Net::Stomp::Producer::Exceptions::CantSerialize;
  48
+use Moose;extends 'Net::Stomp::Producer::Exceptions::BadMessage';
  49
+has '+reason' => ( default => q{couldn't serialize message} );
  50
+__PACKAGE__->meta->make_immutable(inline_constructor=>0);
  51
+}
  52
+
  53
+{
  54
+package Net::Stomp::Producer::Exceptions::BadTransformer;
  55
+use Moose;with 'Throwable',
  56
+    'Net::Stomp::MooseHelpers::Exceptions::Stringy',
  57
+    'Net::Stomp::Producer::Exceptions::StackTrace';
  58
+use namespace::autoclean;
  59
+has transformer => ( is => 'ro', required => 1 );
  60
+
  61
+sub as_string {
  62
+    my ($self) = @_;
  63
+    sprintf qq{%s is not a valid transformer, it doesn't have a "transform" method\n%s},
  64
+        $self->transformer,$self->stack_trace->as_string;
  65
+}
  66
+__PACKAGE__->meta->make_immutable(inline_constructor=>0);
  67
+}
  68
+
  69
+{
  70
+package Net::Stomp::Producer::Exceptions::Invalid;
  71
+use Moose;extends 'Net::Stomp::Producer::Exceptions::BadMessage';
  72
+use namespace::autoclean;
  73
+has transformer => ( is => 'ro', required => 1 );
  74
+has reason => ( is => 'ro', default => q{the message didn't pass validation} );
  75
+
  76
+sub as_string {
  77
+    my ($self) = @_;
  78
+    sprintf "%s (%s): %s\n%s",
  79
+        $self->reason,dump($self->message_body),$self->previous_exception,
  80
+        $self->stack_trace->as_string;
  81
+}
  82
+__PACKAGE__->meta->make_immutable(inline_constructor=>0);
61 83
 }
62 84
 
63 85
 1;

0 notes on commit 6fe104e

Please sign in to comment.
Something went wrong with that request. Please try again.