Tools for Productivity
RESTful Web Services with Mojolicious and DBIx::
                     Class
About Me
Tudor Constantin
● Perl Developer @ Evozon
● http://programming.tudorconstantin.com/
● http://stackoverflow.
  com/users/459233/tudor-constantin
● https://github.com/tudorconstantin
● http://www.linkedin.
  com/in/tudorconstantin
Content
●   Objectives
●   Solutions
●   Implementation
●   Conclusions
Objectives
● Find a way to create generic, distributed DB
  oriented applications
● One backend, multiple frontends, same
  functionality:
  ○ web
  ○ mobile
  ○ desktop
● Rapid app development for the backend
  ○   Avoid boilerplate code
  ○   Adhere to the DRY principle
  ○   Generate as much code as possible
  ○   Have a predictible API
Solutions
● Implement only the business logic in Perl
● Expose it through an API
  ○   REST
  ○   SOAP
  ○   RPC
  ○   WSDL
● Services Oriented Architecture
Solutions
Chosen one is the REST architecture:
● The simplest to implement (from server and
  client perspective)
● Uniform interface
   ○ simplifies and decouples the architecture
● Stateless - each request can be treated on a
  different machine
   ○ Horizontal scalability
Implementation
RESTful routes:

GET /api/user/1

UPDATE /api/user/5

DELETE /api/user/3
Implementation
Define Mojolicious routes:

$r->get('/api/user/:id')->to('user#show')->name('user_details');

$r->put('/api/user/:id')->to('user#update')->name('user_update');



Mojolicious routes are in a 1 to 1 correlation
with the REST ones
Implementation
Methods needed to implement for each
resource:
● list - returns a collection of resources (list of
  users)
● show - return an individual resource (1
  user)
● create - create a new resource
● delete
● update
Implementation
The above operations:
● each corresponds to a DB CRUD operation

● each can get implemented in a controller
  method

● each can be implemented in a generic way:
  ○ get parameters, do stuff, return json
Implementation - Overview
Implementation
sub update{
  my $self = shift;

 my $result_rs = $self->app->model
   ->resultset( $self->{resource} )
   ->search_rs(
       { id => $self->param('id') },
   );

 return $self->render_not_found
      if ( scalar( ( $result_rs->all ) ) == 0 );

$result_rs->update_all( $self->{_payload} );
$result_rs->result_class('DBIx::Class::ResultClass::
HashRefInflator');
  my @result = $result_rs->all();
  return $self->render_json( @result );
}
Steps for having REST
1. Create the DB tables
2. Generate the DBIx::Class models with
   DBIx::Class::Schema::Loader
   a. add the relationships between models
3. Create the controllers which inherit from the
   Base controller
4. (optional) Override the desired methods (ie -
   customize the business logic)
5. Create the routes to Mojolicious
Conclusions
● Very fast to develop
  ○ There are only 6 steps
    ■ 4 of them are, or can be, automated
● Completely DRY
  ○ define the table structure only once - when it is
    created
  ○ you write a column name only when you need to do
    something special with it (validate for example)
● Very easy to test
  ○ end to end testing can be done with simple curl
    operations
End
Sample app (with the generic controller) can be
found on github:
https://github.com/tudorconstantin/expense-
tracker

The generic controller:
https://github.com/tudorconstantin/expense-
tracker/blob/master/lib/ExpenseTracker/Cont
rollers/Base.pm

Perl Tools for Productivity

  • 1.
    Tools for Productivity RESTfulWeb Services with Mojolicious and DBIx:: Class
  • 2.
    About Me Tudor Constantin ●Perl Developer @ Evozon ● http://programming.tudorconstantin.com/ ● http://stackoverflow. com/users/459233/tudor-constantin ● https://github.com/tudorconstantin ● http://www.linkedin. com/in/tudorconstantin
  • 3.
    Content ● Objectives ● Solutions ● Implementation ● Conclusions
  • 4.
    Objectives ● Find away to create generic, distributed DB oriented applications ● One backend, multiple frontends, same functionality: ○ web ○ mobile ○ desktop ● Rapid app development for the backend ○ Avoid boilerplate code ○ Adhere to the DRY principle ○ Generate as much code as possible ○ Have a predictible API
  • 5.
    Solutions ● Implement onlythe business logic in Perl ● Expose it through an API ○ REST ○ SOAP ○ RPC ○ WSDL ● Services Oriented Architecture
  • 6.
    Solutions Chosen one isthe REST architecture: ● The simplest to implement (from server and client perspective) ● Uniform interface ○ simplifies and decouples the architecture ● Stateless - each request can be treated on a different machine ○ Horizontal scalability
  • 7.
  • 8.
  • 9.
    Implementation Methods needed toimplement for each resource: ● list - returns a collection of resources (list of users) ● show - return an individual resource (1 user) ● create - create a new resource ● delete ● update
  • 10.
    Implementation The above operations: ●each corresponds to a DB CRUD operation ● each can get implemented in a controller method ● each can be implemented in a generic way: ○ get parameters, do stuff, return json
  • 11.
  • 12.
  • 14.
    sub update{ my $self = shift; my $result_rs = $self->app->model ->resultset( $self->{resource} ) ->search_rs( { id => $self->param('id') }, ); return $self->render_not_found if ( scalar( ( $result_rs->all ) ) == 0 ); $result_rs->update_all( $self->{_payload} ); $result_rs->result_class('DBIx::Class::ResultClass:: HashRefInflator'); my @result = $result_rs->all(); return $self->render_json( @result ); }
  • 15.
    Steps for havingREST 1. Create the DB tables 2. Generate the DBIx::Class models with DBIx::Class::Schema::Loader a. add the relationships between models 3. Create the controllers which inherit from the Base controller 4. (optional) Override the desired methods (ie - customize the business logic) 5. Create the routes to Mojolicious
  • 16.
    Conclusions ● Very fastto develop ○ There are only 6 steps ■ 4 of them are, or can be, automated ● Completely DRY ○ define the table structure only once - when it is created ○ you write a column name only when you need to do something special with it (validate for example) ● Very easy to test ○ end to end testing can be done with simple curl operations
  • 17.
    End Sample app (withthe generic controller) can be found on github: https://github.com/tudorconstantin/expense- tracker The generic controller: https://github.com/tudorconstantin/expense- tracker/blob/master/lib/ExpenseTracker/Cont rollers/Base.pm