File Coverage

blib/lib/XAS/Lib/Stomp/POE/Client.pm
Criterion Covered Total %
statement 15 88 17.0
branch 0 20 0.0
condition n/a
subroutine 5 15 33.3
pod 9 9 100.0
total 29 132 21.9


line stmt bran cond sub pod time code
1             package XAS::Lib::Stomp::POE::Client;
2              
3             our $VERSION = '0.04';
4              
5 1     1   800 use POE;
  1         2  
  1         8  
6 1     1   254 use Try::Tiny;
  1         2  
  1         56  
7 1     1   387 use XAS::Lib::Stomp::Utils;
  1         2  
  1         23  
8 1     1   399 use XAS::Lib::Stomp::POE::Filter;
  1         2  
  1         56  
9              
10             use XAS::Class
11 1         11 debug => 0,
12             version => $VERSION,
13             base => 'XAS::Lib::Net::POE::Client',
14             mixins => 'XAS::Lib::Mixins::Keepalive',
15             utils => 'trim',
16             accessors => 'stomp',
17             vars => {
18             PARAMS => {
19             -host => { optional => 1, default => undef },
20             -port => { optional => 1, default => undef },
21             -alias => { optional => 1, default => 'stomp-client' },
22             -login => { optional => 1, default => 'guest' },
23             -passcode => { optional => 1, default => 'guest' },
24             }
25             }
26 1     1   5 ;
  1         1  
27              
28             #use Data::Dumper;
29              
30             # ----------------------------------------------------------------------
31             # Public Events
32             # ----------------------------------------------------------------------
33              
34             # ---------------------------------------------------------------------
35             # Public Methods
36             # ---------------------------------------------------------------------
37              
38             sub session_initialize {
39 0     0 1   my $self = shift;
40              
41 0           my $alias = $self->alias;
42              
43 0           $self->log->debug("$alias: session_initialize()");
44              
45             # public events
46              
47 0           $self->log->debug("$alias: doing public events");
48              
49 0           $poe_kernel->state('handle_noop', $self);
50 0           $poe_kernel->state('handle_error', $self);
51 0           $poe_kernel->state('handle_message', $self);
52 0           $poe_kernel->state('handle_receipt', $self);
53 0           $poe_kernel->state('handle_connected', $self);
54              
55             # walk the chain
56              
57 0           $self->SUPER::session_initialize();
58              
59 0           $self->log->debug("$alias: leaving session_initialize()");
60              
61             }
62              
63             sub session_shutdown {
64 0     0 1   my $self = shift;
65              
66 0           my $alias = $self->alias;
67 0           my $frame = $self->stomp->disconnect(
68             -receipt => 'disconnecting'
69             );
70              
71 0           $self->log->debug("$alias: entering session_shutdown()");
72              
73 0           $poe_kernel->call($alias, 'write_data', $frame);
74              
75             # walk the chain
76              
77 0           $self->SUPER::session_shutdown();
78              
79 0           $self->log->debug("$alias: leaving session_shutdown()");
80              
81             }
82              
83             # ---------------------------------------------------------------------
84             # Public Events
85             # ---------------------------------------------------------------------
86              
87             sub handle_connection {
88 0     0 1   my ($self) = $_[OBJECT];
89              
90 0           my $alias = $self->alias;
91 0           my $frame = $self->stomp->connect(
92             -login => $self->login,
93             -passcode => $self->passcode
94             );
95              
96 0           $self->log->debug("$alias: entering handle_connection()");
97              
98 0           $poe_kernel->post($alias, 'write_data', $frame);
99              
100 0           $self->log->debug("$alias: leaving handle_connection()");
101              
102             }
103              
104             sub handle_connected {
105 0     0 1   my ($self, $frame) = @_[OBJECT, ARG0];
106              
107 0           my $alias = $self->alias;
108              
109 0           $self->log->debug("$alias: entering handle_connected()");
110              
111 0 0         if ($self->tcp_keepalive) {
112              
113 0           $self->log->info_msg('tcp_keepalive_enabled', $alias);
114              
115 0           $self->init_keepalive();
116 0           $self->enable_keepalive($self->socket);
117              
118             }
119              
120 0           $self->log->info_msg('net_server_connected', $alias, $self->host, $self->port);
121              
122 0           $poe_kernel->post($alias, 'connection_up');
123              
124 0           $self->log->debug("$alias: leaving handle_connected()");
125              
126             }
127              
128             sub handle_message {
129 0     0 1   my ($self, $frame) = @_[OBJECT, ARG0];
130              
131             }
132              
133             sub handle_receipt {
134 0     0 1   my ($self, $frame) = @_[OBJECT, ARG0];
135              
136             }
137              
138             sub handle_error {
139 0     0 1   my ($self, $frame) = @_[OBJECT, ARG0];
140              
141 0           my $message = '';
142 0           my $message_id = '';
143 0           my $alias = $self->alias;
144              
145 0 0         if ($frame->header->methods->has('message_id')) {
146              
147 0           $message_id = $frame->header->message_id;
148              
149             }
150              
151 0 0         if ($frame->header->methods->has('message')) {
152              
153 0           $message = $frame->header->message;
154              
155             }
156              
157 0           $self->log->error_msg('stomp_errors',
158             $alias,
159             trim($message_id),
160             trim($message),
161             trim($frame->body)
162             );
163              
164             }
165              
166             sub handle_noop {
167 0     0 1   my ($self, $frame) = @_[OBJECT, ARG0];
168              
169 0           my $alias = $self->alias;
170              
171 0           $self->log->debug("$alias: handle_noop()");
172              
173             }
174              
175             # ---------------------------------------------------------------------
176             # Private Events
177             # ---------------------------------------------------------------------
178              
179             sub _server_message {
180 0     0     my ($self, $frame, $wheel_id) = @_[OBJECT, ARG0, ARG1];
181              
182 0           my $alias = $self->alias;
183              
184 0           $self->log->debug("$alias: entering _server_message()");
185              
186 0 0         if ($frame->command eq 'CONNECTED') {
    0          
    0          
    0          
    0          
187              
188 0           $self->log->debug("$alias: received a \"CONNECTED\" message");
189 0           $poe_kernel->post($alias, 'handle_connected', $frame);
190              
191             } elsif ($frame->command eq 'MESSAGE') {
192              
193 0           $self->log->debug("$alias: received a \"MESSAGE\" message");
194 0           $poe_kernel->post($alias, 'handle_message', $frame);
195              
196             } elsif ($frame->command eq 'RECEIPT') {
197              
198 0           $self->log->debug("$alias: received a \"RECEIPT\" message");
199 0           $poe_kernel->post($alias, 'handle_receipt', $frame);
200              
201             } elsif ($frame->command eq 'ERROR') {
202              
203 0           $self->log->debug("$alias: received an \"ERROR\" message");
204 0           $poe_kernel->post($alias, 'handle_error', $frame);
205              
206             } elsif ($frame->command eq 'NOOP') {
207              
208 0           $self->log->debug("$alias: received an \"NOOP\" message");
209 0           $poe_kernel->post($alias, 'handle_noop', $frame);
210              
211             } else {
212              
213 0           $self->log->warn_msg('stomp_unknown_type', $alias, $frame->command);
214              
215             }
216              
217 0           $self->log->debug("$alias: leaving _server_message()");
218              
219             }
220              
221             # ---------------------------------------------------------------------
222             # Private Methods
223             # ---------------------------------------------------------------------
224              
225             sub init {
226 0     0 1   my $class = shift;
227              
228 0           my $self = $class->SUPER::init(@_);
229              
230 0 0         unless (defined($self->{'host'})) {
231              
232 0           $self->{'host'} = $self->env->mqserver;
233              
234             }
235              
236 0 0         unless (defined($self->{'port'})) {
237              
238 0           $self->{'port'} = $self->env->mqport;
239              
240             }
241              
242 0           $self->{'stomp'} = XAS::Lib::Stomp::Utils->new();
243 0           $self->{'filter'} = XAS::Lib::Stomp::POE::Filter->new();
244              
245 0           return $self;
246              
247             }
248              
249             1;
250              
251             __END__
252              
253             =head1 NAME
254              
255             XAS::Lib::Stomp::POE::Client - A STOMP client for the POE Environment
256              
257             =head1 SYNOPSIS
258              
259             This module is a class used to create clients that need to access a
260             message server that communicates with the STOMP protocol. Your program could
261             look as follows:
262              
263             package Client;
264              
265             use POE;
266             use XAS::Class
267             version => '1.0',
268             base => 'XAS::Lib::Stomp::POE::Client',
269             ;
270              
271             package main;
272              
273             use POE;
274             use strict;
275              
276             Client->new(
277             -alias => 'testing',
278             -queue => '/queue/testing',
279             );
280              
281             $poe_kernel->run();
282              
283             exit 0;
284              
285             =head1 DESCRIPTION
286              
287             This module handles the nitty-gritty details of setting up the communications
288             channel to a message queue server. You will need to sub-class this module
289             with your own for it to be useful.
290              
291             When messages are received, specific events are generated. Those events are
292             based on the message type. If you are interested in those events you should
293             override the default behavior for those events. The default behavior is to
294             do nothing. This module inherits from L<XAS::Lib::Net::POE::Client|XAS::Lib::Net::POE::Client>.
295              
296             =head1 METHODS
297              
298             =head2 new
299              
300             This method initializes the class and starts a session to handle the
301             communications channel. It takes the following additional parameters:
302              
303             =over 4
304              
305             =item B<-alias>
306              
307             Sets the alias for this client, defaults to 'stomp-client'.
308              
309             =item B<-host>
310              
311             Sets the host to attach too. defaults to 'localhost'.
312              
313             =item B<-port>
314              
315             Sets the port to use, defaults to 61613.
316              
317             =item B<-login>
318              
319             Sets the login name for this server, defaults to 'guest'.
320              
321             =item B<-passcode>
322              
323             Sets the passcode for this server, defaults to 'guest'.
324              
325             =back
326              
327             =head2 handle_connection(OBJECT)
328              
329             This event is signaled and the corresponding method is called upon initial
330             connection to the message server. I accepts these parameters:
331              
332             =over 4
333              
334             =item B<OBJECT>
335              
336             The current class object.
337              
338             =back
339              
340             =head2 handle_connected(OBJECT, ARG0)
341              
342             This event and corresponding method is called when a "CONNECT" frame is
343             received from the server. It posts the frame to the 'connection_up' event.
344             It accepts these parameters:
345              
346             =over 4
347              
348             =item B<OBJECT>
349              
350             The current class object.
351              
352             =item B<ARG0>
353              
354             The current STOMP frame.
355              
356             =back
357              
358             =head2 handle_message(OBJECT, ARG0)
359              
360             This event and corresponding method is used to process "MESSAGE" frames.
361              
362             It accepts these parameters:
363              
364             =over 4
365              
366             =item B<OBJECT>
367              
368             The current class object.
369              
370             =item B<ARG0>
371              
372             The current STOMP frame.
373              
374             =back
375              
376             Example
377              
378             sub handle_message {
379             my ($self, $frame) = @_[OBJECT,ARG0];
380            
381             my $nframe = $self->stomp->ack(
382             -message_id => $frame->header->message_id
383             );
384              
385             $poe_kernel->yield('write_data', $nframe);
386              
387             }
388              
389             This example really doesn't do much other then "ack" the messages that are
390             received.
391              
392             =head2 handle_receipt(OBJECT, ARG0)
393              
394             This event and corresponding method is used to process "RECEIPT" frames.
395             It accepts these parameters:
396              
397             =over 4
398              
399             =item B<OBJECT>
400              
401             The current class object.
402              
403             =item B<ARG0>
404              
405             The current STOMP frame.
406              
407             =back
408              
409             Example
410              
411             sub handle_receipt {
412             my ($self, $frame) = @_[OBJECT,ARG0];
413              
414             my $receipt = $frame->header->receipt;
415              
416             }
417              
418             This example really doesn't do much, and you really don't need to worry about
419             receipts unless you ask for one when you send a frame to the server. So this
420             method could be safely left with the default.
421              
422             =head2 handle_error(OBJECT, ARG0)
423              
424             This event and corresponding method is used to process "ERROR" frames.
425             It accepts these parameters:
426              
427             =over 4
428              
429             =item B<OBJECT>
430              
431             The current class object.
432              
433             =item B<ARG0>
434              
435             The current STOMP frame.
436              
437             =back
438              
439             =head2 handle_noop(OBJECT, ARG0)
440              
441             This event and corresponding method is used to process "NOOP" frames.
442             It accepts these parameters:
443              
444             =over 4
445              
446             =item B<OBJECT>
447              
448             The current class object.
449              
450             =item B<ARG0>
451              
452             The current STOMP frame.
453              
454             =back
455              
456             =head1 ACCESSORS
457              
458             =head2 stomp
459              
460             This returns an object to the internal L<XAS::Lib::Stomp::Utils|XAS::Lib::Stomp::Utils>
461             object. This is very useful for creating STOMP frames.
462              
463             Example
464              
465             $frame = $self->stomp->connect(
466             -login => 'testing',
467             -passcode => 'testing'
468             );
469              
470             $poe_kernel->yield('write_data', $frame);
471              
472             =head1 SEE ALSO
473              
474             =over 4
475              
476             =item L<XAS|XAS>
477              
478             =back
479              
480             For details on the protocol see L<http://stomp.github.io/>.
481              
482             =head1 AUTHOR
483              
484             Kevin L. Esteb, E<lt>=[@kesteb.usE<gt>
485              
486             =head1 COPYRIGHT AND LICENSE
487              
488             Copyright (C) 2014 Kevin L. Esteb
489              
490             This is free software; you can redistribute it and/or modify it under
491             the terms of the Artistic License 2.0. For details, see the full text
492             of the license at http://www.perlfoundation.org/artistic_license_2_0.
493              
494             =cut