HomePage RecentChanges Ext.Direct

A set of perl implementation of the Ext.Direct server side stack.

See Also

Live Demonstrations


The implementations

Simple

The code in the simple/ directory is a short but fully functional implementation. It uses a single config file, one CGI for generate the Javascript API description and one to do the routing. It has a very simple view of class and method requests.

This has really been written as a reference implementation for Perl.

Features

Mod Perl

A far more complete and reliable version of the system, which I will use in production.

Features

Future

Example config

Apache configuration:

	PerlModule Apache::RPC::ExtDirect
	<Location /data>
		SetHandler modperl
		PerlResponseHandler Apache::RPC::ExtDirect
		PerlSetVar ConfigFile /full/path/to/config.pl
	</Location>

Config file: (perl format)

{
        Lookup => {
                Class => 'Demo',
                Methods => {
                        suburb => { params => 1 },
                },
        },
}

Out of the box

Introspection... soft of

I would like to write a module like this:

package Demo::Package;
use Attribute::RPC::ExtDirect;
sub calculate : ExtDirect(3) {
   my ($a, $b, $c) = @_;
   return $a * $b * $c;
}
1;

The idea is to use attributes in Perl to allow self description of the module within itself. The mod_perl apache implementation now supports reading configuration from the module. Just specify the package name (currently limited to support modules with '::' in their identifier) instead of a filename.

Attribute::RPC::ExtDirect could then create the configuration by providing a method (e.g. extdirect_config) which can also be used to dump the data if not loaded through Apache. Therefore the attribute module can be used in any of the implementations :-)

This should then be tested with Moose and other object frameworks.


How to write an Ext.Direct Server Stack

NOTE: This code here is not meant to be complete. Please see the Source Code on Git hub for a complete working version. This code has many missing components and here is for description rather than accuracy.

There are three steps in writing a server stack.

Config

If you want to keep all the configuration and information about the API on the server side, you really have two choices:

I have gone for configuration, as I desire more control over each interface. E.g. having high level restrictions, such as access controls before the class is even loaded. Therefore introspection is not much help to me.

But when exposing more complicated APIs with less control, it could be very useful.

This example shows some configuration using perl data format.

#!Perl
{
        Profile => {
                getBasicInfo => { params => 2 },
                getPhoneInfo => { params => 1 },
                getLocationInfo => { params => 1 },
                updateBasicInfo => { params => 2, formHandler => 1, },
        },
};

API

The API is used by most of the example/reference implementations as the name given to the Javascript file generated.

Example:

#!Perl
my $CONFIG = do "config.pl";

my $actions = {};
foreach my $class (keys %$CONFIG) {
        my @methods;
        foreach my $method (keys %{$CONFIG->{$class}}) {
                push @methods, {
                        name => $method,
                        len => $CONFIG->{$class}{$method}{params},
                };
        }
        $actions->{$class} = \@methods;
}

my $url = $ENV{SCRIPT_NAME};
$url =~ s/api/router/;

print header(-type => 'text/plain');
print "Ext.app.REMOTING_API = ";
print to_json({
        url => $url,
        type => 'remoting',
        actions => $actions,
});

Router

The router has only a few small jobs (minimum implementation)

Example:

#!Perl

my $CONFIG = do "config.pl";


my $buf;
read STDIN, $buf, $ENV{CONTENT_LENGTH};
my $data from_json($buf);
if (ref($data) ne "ARRAY") {
        $data = [ $data ];
}

my @results;
foreach my $request (@$data) {
        my $action = $request->{action};
        my $method = $request->{method};
        my $data = $request->{data};

        unless ($CONFIG->{$action}{$method}) {
                die "BAD REQUEST - Invalid action/method - $action/$method";
        }
        my $class = "Demo";
        my $obj = $class->new();
        my $result = $obj->$method(ref($data) eq "ARRAY" ? @$data : ());
        
        push @results, {
                type => 'rpc',
                tid => $request->{tid},
                action => $action,
                method => $method,
                result => $result,
        };
}

print "Content-type: text/plain\n\n";
print to_json(\@results);

Example code:

#!Perl
sub calc : ExtDirect(3) {
        my ($x, $y, $z) = @_;
        return ($x * $y * $z);
}

Software error:

Can't locate object method "endform" via package "CGI" at /data/scott.dd.com.au/wiki/modules/search.pl line 15.

For help, please send mail to the webmaster (webmaster@dd.com.au), giving this error message and the time and date of the error.