File Coverage

blib/lib/JSON/RPC/Dispatcher/ClassMapping.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package JSON::RPC::Dispatcher::ClassMapping;
2              
3 1     1   18638 use strict;
  1         3  
  1         27  
4 1     1   4 use warnings;
  1         2  
  1         47  
5             our $VERSION = '0.03';
6              
7 1     1   395 use JSON::RPC::Dispatcher 0.0505;
  0            
  0            
8             use Moose;
9             use namespace::autoclean;
10              
11             # XXX: Hack to relax "method" constraint of J::R::D::P so that it accepts "."
12             {
13             package
14             JSON::RPC::Dispatcher::Procedure; # hide from PAUSE/indexers
15             use Moose;
16              
17             __PACKAGE__->meta->make_mutable;
18             has method => (
19             is => 'rw',
20             default => undef,
21             trigger => sub {
22             my ($self, $new, $old) = @_;
23             if (defined $new && $new !~ m{^[A-Za-z0-9_.]+$}xms) {
24             $self->invalid_request($new.' is not a valid method name.');
25             }
26             },
27             );
28             no Moose;
29             __PACKAGE__->meta->make_immutable;
30             }
31              
32              
33             has 'rpc' => (
34             is => 'rw',
35             isa => 'Object',
36             default => sub { JSON::RPC::Dispatcher->new },
37             handles => [ 'to_app', 'register' ],
38             );
39              
40             has 'dispatch' => (
41             is => 'rw',
42             isa => 'HashRef[Str]',
43             required => 1,
44             );
45              
46              
47             sub BUILD {
48             my $self = shift;
49              
50             # setup dispatch to methods of classes defined in %dispatch
51             while (my ($namespace, $module) = each %{ $self->dispatch }) {
52             Class::MOP::load_class($module);
53             my $metaclass = Class::MOP::Class->initialize($module);
54             foreach my $method ($metaclass->get_method_list) {
55             $self->register("$namespace.$method", sub { $module->$method(@_) })
56             if substr($method, 0, 1) ne '_';
57             }
58             }
59             }
60              
61             __PACKAGE__->meta->make_immutable;
62              
63             1;
64              
65             __END__
66              
67             =head1 NAME
68              
69             JSON::RPC::Dispatcher::ClassMapping - Expose all public methods of classes as RPC methods
70              
71             =head1 SYNOPSIS
72              
73             # in app.psgi
74             use JSON::RPC::Dispatcher::ClassMapping;
75              
76             my $server = JSON::RPC::Dispatcher::ClassMapping->new(
77             dispatch => {
78             Foo => 'My::Module',
79             Bar => 'My::Another::Module',
80             },
81             );
82              
83             $server->to_app;
84              
85             =head1 DESCRIPTION
86              
87             This module is a wrapper for L<JSON::RPC::Dispatcher> and provides an
88             easy way to expose all public methods of classes as JSON-RPC methods. It
89             treats methods with a leading underscore as private methods.
90              
91             =head1 ATTRIBUTES
92              
93             =over 4
94              
95             =item I<dispatch>
96              
97             This is a hashref that maps "package names" in RPC method requests
98             to actual Perl module names (in a format like C<My::Module::Name>).
99             For example, let's say that you have a C<dispatch> that looks like this:
100              
101             {
102             'Util' => 'Foo::Service::Util',
103             'Calendar' => 'Bar::Baz'
104             }
105              
106             So then, calling the method C<Util.get> will call
107             C<< Foo::Service::Util->get >>. Calling C<Calendar.create> will call
108             C<< Bar::Baz->create >>. You don't have to pre-load the Perl modules,
109             JSON::RPC::Dispatcher::ClassMapping will load them for you.
110              
111             =back
112              
113             =head1 AUTHOR
114              
115             Sherwin Daganato E<lt>sherwin@daganato.comE<gt>
116              
117             Based on the dispatcher of L<RPC::Any::Server> by Max Kanat-Alexander.
118              
119             =head1 LICENSE
120              
121             This library is free software; you can redistribute it and/or modify it
122             under the same terms as Perl itself.
123              
124             =head1 SEE ALSO
125              
126             L<RPC::Any::Server> L<SOAP::Server>
127              
128             =cut