Alex Tokarev > RPC-ExtDirect-2.13 > RPC::ExtDirect

Download:
RPC-ExtDirect-2.13.tar.gz

Dependencies

Annotate this POD

View/Report Bugs
Module Version: 2.13   Source   Latest Release: RPC-ExtDirect-2.15

NAME ^

RPC::ExtDirect - Expose Perl code to Ext JS RIA applications through Ext.Direct remoting

SYNOPSIS ^

 package Foo::Bar;
 
 use RPC::ExtDirect Action => 'Fubar',
                    before => \&package_before_hook,
                    after  => \&package_after_hook,
                    ;
  
 sub foo_custom_hook {
    # Check something, return true
    return 1;
 }
 
 sub foo : ExtDirect(2, before => \&foo_custom_hook) {
    my ($class, $arg1, $arg2) = @_;
  
    # do something, store results in scalar
    my $result = ...;
  
    return $result;
 }
  
 # This method doesn't need hooks for some reason
 sub bar
    : ExtDirect(
        params => ['foo', 'bar'], before => 'NONE', after => 'NONE',
      )
 {
    my ($class, %arg) = @_;
  
    my $foo = $arg{foo};
    my $bar = $arg{bar};
  
    # do something, returning scalar
    my $result = eval { ... };
  
    # or throw an exception if something's wrong
    die "Houston, we've got a problem: $@\n" if $@;
  
    return $result;
 }
  
 sub baz : ExtDirect(formHandler) {
    my ($class, %arg) = @_;
  
    my @form_fields    = grep { !/^file_uploads$/  } keys %arg;
    my @uploaded_files = @{ $arg{file_uploads}     };
  
    # do something with form fields and files
    my $result = { ... };
  
    return $result;
 }
  
 sub package_before_hook {
    my ($class, %params) = @_;
  
    # Unpack parameters
    my ($method, $env) = @params{ qw/method _env/ };
  
    # Decide if user is authorized to call this method
    my $authorized = check_authorization($method, $env);
  
    # Positive
    return 1 if $authorized;
  
    # Negative, return error string
    return 'Not authorized';
 }
  
 sub package_after_hook {
    my ($class, %params) = @_;
  
    # Unpack parameters
    my ($method, $result, $ex) = @params{ qw/method result exception/ };
    
    # Log the action
    security_audit_log($method, $result, $ex);
 }

DESCRIPTION ^

Abstract

This module provides an easy way to map Perl code to Ext.Direct RPC interface used with Ext JS JavaScript framework.

What Ext.Direct is for?

Ext.Direct is a high level RPC protocol that allows easy and fast integration of server components with JavaScript interface. Client side stack is built in Ext JS core and is used by many components like data Stores, Forms, Grids, Charts, etc. Ext.Direct supports request batching, file uploads, event polling and many other features.

Besides simplicity and ease of use, Ext.Direct allows to achieve very clean code and issue separation both on server and client sides, which in turn results in simplified code, greater overall software quality and shorter development times.

From Perl module developer perspective, Ext.Direct is just a method attribute; it doesn't matter if it's called from Perl code or through Ext.Direct. This approach, in particular, allows for multi-tiered testing:

For more information on Ext.Direct, see http://www.sencha.com/products/extjs/extdirect/.

Terminology

Ext.Direct uses the following terms, followed by their descriptions:

Configuration

Description of server side calls exposed to client side. Includes information on Action and Method names, as well as argument number and/or names

API

JavaScript chunk that encodes Configuration. Usually generated by application server and retrieved by client once upon startup. Another option is to embed API declaration in client side application code.

Router

Server side component that receives remoting calls, dispatches requests, collects and returns call Results or Exceptions.

Action

Namespace unit; collection of Methods. The nearest Perl analog is package, other languages may call it a Class. Since the actual calling code is JavaScript, Action names should conform to JavaScript naming rules (i.e. no '::', use dots instead).

Method

Subroutine exposed through Ext.Direct API to be called by client side. Method is fully qualified by Action and Method names using dot as delimiter: Action.Method.

Result

Any data returned by Method upon successful or unsuccessful call completion. This includes application logic errors. 'Not authenticated' and alike events should be returned as Results, not Exceptions.

Exception

Fatal error, or any other unrecoverable event in application code. Calls that produce Exception instead of Result are considered unsuccessful; Ext.Direct provides built in mechanism for managing Exceptions.

Exceptions are not used to indicate errors in application logic flow, only for catastrophic conditions. Nearest analog is status code 500 for HTTP responses.

Examples of Exceptions are: request JSON is broken and can't be decoded; called Method dies because of internall error; Result cannot be encoded in JSON, etc.

Event

An asynchronous notification that can be generated by server side and passed to client side, resulting in some reaction. Events are useful for status updates, progress indicators and other predictably occuring conditions and events.

Event Provider

Server side script that gets polled by client side every N seconds; default N is 3 but it can be changed in client side configuration.

USING RPC::EXTDIRECT ^

In order to export subroutine to ExtDirect interface, use ExtDirect(n, ...) attribute in sub declaration. Note that there can be no space between attribute name and opening parentheses. In Perls older than 5.12, attribute declaration can't span multiple lines, i.e. the whole ExtDirect(n, ...) should fit in one line.

n is mandatory calling convention declaration; it may be one of the following options:

Optional method attributes can be specified after calling convention declaration, in hash-like key => value form. Optional attributes are:

METHODS ^

Unlike Ext.Direct specification (and reference PHP implementation, too) RPC::ExtDirect does not impose strict architectural notation on server side code. There is no mandatory object instantiation and no assumption about the code called. That said, an RPC::ExtDirect Method should conform to the following conventions:

HOOKS ^

Hooks provide an option to intercept method calls and modify arguments passed to the methods, or cancel their execution. Hooks are intended to be used as a shim between task-oriented Methods and Web specifics.

Methods should not, to the reasonable extent, be aware of their environment or care about it; Hooks are expected to know how to deal with Web intricacies but not be task oriented.

The best uses for Hooks are: application or package-wide pre-call setup, user authorization, logging, cleanup, testing, etc.

A hook is a Perl subroutine (can be anonymous, too). Hooks can be of three types:

Hooks can be defined on three levels, in order of precedence: method, package and global. For each Method, only one hook of each type can be applied. Hooks specified in Method definition take precedence over all other; if no method hook is found then package hook applies; and if there is no package hook then global hook gets called, if any. To avoid using hooks for a particular method, use 'NONE' instead of coderef; this way you can specify global and/or package hooks and exclude some specific Methods piecemeal.

Hooks are subject to the following calling conventions:

ENVIRONMENT OBJECTS ^

Since Hooks, and sometimes Methods too, need to be aware of their Web environment, it is necessary to give them access to it in some way without locking on platform specifics. The answer for this problem is environment objects.

An environment object provides platform-agnostic interface for accessing HTTP headers, cookies, form fields, etc, by duck typing. Such object is guaranteed to have the same set of methods that behave the same way across all platforms supported by RPC::ExtDirect, avoiding portability issues.

The interface is modeled after de facto standard CGI.pm:

Of course it is possible to use environment object in a more sophisticated way if you like to, however do not rely on it having a well-known class name as it is not guaranteed.

FILE UPLOADS ^

Ext.Direct offers native support for file uploading by using temporary forms. RPC::ExtDirect supports this feature; upload requests can be processed in a formHandler Method. The interface aims to be platform agnostic and will try to do its best to provide the same results in all HTTP environments supported by RPC::ExtDirect.

In a formHandler Method, arguments are passed as a hash. If one or more file uploads were associated with request, the argument hash will contain 'file_uploads' key with value set to arrayref of file hashrefs. Each file hashref will have the following keys:

type

MIME type of the file

size

file size, in octets

path

path to temporary file that holds uploaded content

handle

opened IO::Handle for temporary file

basename

name portion of original file name

filename

full original path as sent by client

All files passed to a Method need to be processed in that Method; existence of temporary files is not guaranteed after Method returns.

CAVEATS ^

In order to keep this module as simple as possible, I had to sacrifice the ability to automatically distinguish inherited class methods. In order to declare inherited class methods as Ext.Direct exportable you have to override them in subclass, like that:

    package foo;
    use RPC::ExtDirect;
    
    sub foo_sub : ExtDirect(1) {
        my ($class, $arg) = @_;
    
        # do something
        ...
    }
    
    package bar;
    use base 'foo';
    
    sub foo_sub : ExtDirect(1) {
        my ($class, $arg) = @_;
    
        # call inherited method
        return __PACKAGE__->SUPER::foo_sub($arg);
    }
    
    sub bar_sub : ExtDirect(2) {
        my ($class, $arg1, $arg2) = @_;
    
        # do something
        ...
    }

On the other hand if you don't like class-based approach, just don't inherit your packages from one another. In any case, declare your Methods explicitly every time and there never will be any doubt about what Method gets called in any given Action.

DEPENDENCIES ^

RPC::ExtDirect is dependent on the following modules: Attribute::Handlers, "JSON".

BUGS AND LIMITATIONS ^

In version 2.0, ExtDirect attribute was moved to BEGIN phase instead of default CHECK phase. While this improves compatibility with Apache/mod_perl environments, this also causes backwards compatibility problems with Perl older than 5.12. Please let me know if you need to run RPC::ExtDirect 2.0 with older Perls; meanwhile RPC::ExtDirect 1.x will provide compatibility with Perl 5.6.0 and newer.

There are no known bugs in this module. Please report problems to author, patches are welcome.

SEE ALSO ^

Alternative Ext.Direct implementations for Perl: CatalystX::ExtJS::Direct by Moritz Onken, http://github.com/scottp/extjs-direct-perl by Scott Penrose, Dancer::Plugin::ExtDirect by Alessandro Ranellucci.

For Web server gateway implementations, see CGI::ExtDirect and Plack::Middleware::ExtDirect modules based on RPC::ExtDirect engine.

For configurable Ext.Direct API options, see RPC::ExtDirect::API module.

AUTHOR ^

Alexander Tokarev <tokarev@cpan.org>

ACKNOWLEDGEMENTS ^

I would like to thank IntelliSurvey, Inc for sponsoring my work on version 2.0 of RPC::ExtDirect suite of modules.

LICENSE AND COPYRIGHT ^

Copyright (c) 2011-2012 by Alexander Tokarev.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See "perlartistic".

syntax highlighting: