![[ICS] Ivory City Systems](icslogo.png)
|

|
CHECK OUT OUR ARTICLE ON PERL.COM!
PERL.COM MOD_PERLSERVICE
|
mod_perlservice
developed by:
|
Michael Collins
|
| Documentation by: |
Michael Collins |
Questions/Comments/Bugs:
|
michaelcollins@ivorycity.com |
DOWNLOAD
mod_perlservice-1.0.4.tar.gz
Perl
Client | C Client
| Flash
Client
DOCUMENTATION
mod_perlservice?
What is
that?
The cool
new way to do remoting with
Perl and Apache!
But,
lets start by breaking that crazy name apart.
mod - perl - service
mod - It's a module for the
popular and ubiquitous Apache HTTP Server.
perl - Of
course, it's the popular and ubiquitous programming language.
service
- Ah, this is the unique part. It's the new ingredient that unifies
Apache, Perl and XML into an easy to use web-services system.
With the mod_perlservice system, you can write perl subs and packages
on your server and call them over the internet from client code.
Clients can pass scalars, arrays
and hashes to the server-side subroutines and obtain the return value (
scalar, array or hash ) back from the remote code. Some folks refer to
this functionality
as "remoting" or "RPC", so if you like, you can
say mod_perlservice is remoting with Perl and Apache. Client programs
may be written in a variety of languages; libraries for C, Perl, and
Flash Action Script are all ready to go!
Now that you know what
mod_perlservice is, lets look at why it is. The author (That's
me!) believes that mod_perlservice has a very clean, easy-to-use
interface when compared with other RPC systems. Also,
since it builds on the Apache platform, it benefits from
Apache's ubiquity, security, and status as a standard. Since
mod_perlservice sports an embedded perl interpreter, it offers high
performance for demanding applications.
So what can I use
this mod_perlservice for?
You can use it to create networked
applications that require client-server communication, information
processing and sharing. mod_perlservice is for applications and
you will not use it to
create dynamic content for your HTML pages. However, you surely can use
it for Flash remoting with Perl.
Here are some usage
examples:
A desktop application (written using your favorite
C++ GUI library) that records the current local air temperatue and
sends it to an online database every 10 minutes. The server can
be queried to obtain the current and historical local air temperature
of any other participating client.
A Flash-based stock
portfolio management system. You can create model stock portfolios
and retrieve realtime stock quote information and news.
A
command-line utility in Perl that accepts English sentences on
standard input and outputs the sentences in French. Translation
occurs in server-side Perl code. If the sentence is idomatic and the
translation is incorrect, the user has the option of sending the
server a correct translation that will be stored in an online idiom
database.
How
Do
I Get Started?
Okay,
let's move onto the fun stuff and set up a working
installation.
Before we begin, make sure you have everything
you need!
You need an apache webserver available at www.apache.org
You need perl at www.perl.org
You
need expat at expat.sourceforge.net
You need mod_perlservice
You need a mod_perlservice client library: Perl
Client | C Client
| Flash
Client
* You must
download a client library separately! They are not included in the
mod_perlservice distro!
In your build directory:
|
myhost$ tar -xvzf
mod_perlservice.tar.gz
myhost$ cd mod_perlservice
myhost$ ./configure
myhost$ make
myhost$ make install
|
If
everything goes to plan, you'll have
mod_perlservice.so in your apache modules dir, (usually /etc/apache/modules)
Now
we
need to configure
Apache to use mod_perlservice.
cd
into
your apache conf
directory (usually /etc/apache/conf)
Add
the following lines to the file apache.conf:
|
LoadModule perlservice_module
modules/mod_perlservice.so
AddModule mod_perlservice.c
|
Add
the following lines to commonapache.conf:
|
<IfModule mod_perlservice.c>
<Location /perlservice>
SetHandler mod_perlservice
Allow From All
PerlApp myappname /my/app/dir
#Examples
PerlApp stockmarket /home/services/stockmarket
PerlApp temperature /home/services/temperature
</Location>
</IfModule>
|
Pay
close attention the PerlApp directive!
For
every
mod_perlservice application you want to run, you'll need a PerlApp
directive.
So,
if I were creating stock market application, I might create a
directory:
/home/services/stockmarket
and
add the
following
PerlApp directive:
| PerlApp
stockmarket
/home/services/stockmarket |
This
tells mod_perlservice that you would like to host an
application called stockmarket
and that the perl code files will be located in the
/home/services/stockmarket directory. You
may run as many service applications as you wish and you may organize
them however you wish.
Okay, now the config files should be
set! The next step is to restart apache. This is usually done by:
|
myhost$ /etc/init.d/apache restart
or
myhost$ apachectl restart
|
Now
if everything went to plan, mod_perlservice should be
installed! Congratulations!
How 'Bout An Example?
Okay,
lets
create that stock portfolio example we
talked about earlier. We won't implement realtime quotes, but instead
we'll create a static database of some common stock names and
historical prices. Our application will support stock information for
General
Electric (GE), Red Hat (RHAT), Coca Cola (KO), and Caterpillar (CAT).
The
application will be called stockmarket and we should
place all our perl files in the stockmarket application directory
(/home/services/stockmarket). The first file will be "quotes.pm" and
it reads as follows:
our
$lookups = {
"General Electric" => "GE",
"Red Hat" => "RHAT",
"Coca Cola" => "KO",
"Caterpillar Inc" => "CAT"
};
our $stocksymbols = {
"GE" =>{ "Price"=>33.91,
"EarningsPerShare"=>1.544 },
"RHAT"=>{ "Price"=>14.96, "EarningsPerShare"=>0.129 },
"KO" =>{ "Price"=>42.84,
"EarningsPerShare"=>1.984 },
"CAT" =>{ "Price"=>75.74, "EarningsPerShare"=>4.306 }
};
package quotes;
sub
lookupSymbol
{
my $companyname = shift;
return $lookups->{$companyname};
}
sub
getLookupTable
{
return $lookups;
}
sub
getStockPrice
{
my $stocksymbol = shift;
return $stocksymbols->{$stocksymbol}->{"Price"};
}
sub
getAllStockInfo
{
my $stocksymbol = shift;
return $stocksymbols->{$stocksymbol};
}
1; |
Okay,
that's our example server-side program. Basically, we have two
static "databases" ($lookups and $stocksymbols) that serve to provide
information about a limited
universe of stocks. The static databases are queried through the
various above methods; the functionality should be fairly
self-explanatory.
You
may have as many ".pm"
files in your application as you wish and you may also define as many
packages within a ".pm" file as you wish. So an extension to this
application
might be a file called "news.pm" that enables you to fetch current and
historical news about your favorite stocks.
Now let's talk some security. As it stands, this code won't work - mod_perlservice
will restrict access to any file and method you don't explicitly export for public use.
To export stuff we use the .serviceaccess file. Create this file in each
application directory you declare with mod_perlservice or you'll have zero access.
Example .serviceaccess file
<ServiceAccess>
<AllowFile name="quotes.pm">
Allow quotes::*
</AllowFile>
</ServiceAccess> |
So this file would be /home/services/stockmarket/.serviceaccess because this
is where our application resides. IMPORTANT: the apache user should NOT own this file,
it could be bad for security.
The above file allows access to the file quotes.pm
and allows public access to all (*) the methods in package quotes.
If you just wanted
to allow access to getStockPrice, you would have put Allow quotes::getStockPrice.
Then after, you could add access to lookupSymbol by adding Allow quotes::lookupSymbol.
To make this file public carte-blanche, you could put Allow *. You
won't need to restart apache when you make changes to this file, it reloads automatically.
Client Code
Well,
so far I've only shown you half the story. Now let's create
some client side code. Our client example uses the Flash "PerlService"
library, just one of the client-side interfaces to mod_perlservice (
there are clients for Perl and C as well).
The Flash client was developed for browser interfaces while the perl
and C clients would be used to create command line, or GUI ( ie GTK or
Qt ) applications. This article is on the web, so we'll give
the Flash interface a spin and then go through an example in Perl.
Flash
Client
The
first
code
smidgen should be located in the first root frame of
your Flash application. Below, we basically instantiate the global
PerlService object and create event handlers that get called when
remote method calls return from the server. The event handlers output
the requested stock information to the display box.
#include
"PerlService-0.0.2.as"
// Create a
global
PerlService object
// Tell the
PerlService
object about the remote code we want to use:
// arg1) host:
www.ivorycity.com
// arg2)
application:
stockmarket
// arg3) file:
quotes.pm
// arg4)
package:
quotes
_global.ps =
new
PerlService("www.ivorycity.com","stockmarket","quotes.pm","quotes");
// First
declare
three
callback functions to handle return values
function
onStockPrice(val)
{
output.text =
"StockPrice: " + symbolInput.text + " " + val +
"\n" + output.text;
}
function
onAllStockInfo(val)
{
output.text =
"Stock
Info: " + allInfoInput.text + "\n" +
"\tPrice: " + val.Price +
"\n" +
"\tEarnings Per Share: " +
val.EarningsPerShare + "\n" +
+ output.text;
}
function
onLookupSymbol(val)
{
output.text =
"Lookup Result: " + symbolInput.text + " " + val +
"\n" + output.text;
}
// Register
callback
handlers for managing the return values from the
remote methods
// ie.
onStockPrice
receives the return value from remote method
getStockPrice
ps.registerReplyHandler(
"getStockPrice", onStockPrice );
ps.registerReplyHandler(
"getAllStockInfo", onAllStockInfo );
ps.registerReplyHandler(
"lookupSymbol", onLookupSymbol );
|
Now
for
the code
that makes things happen! The following code is
attached to
three separate buttons. When clicked, the buttons call the remote perl
methods using the
global PerlService object. Flash Action Script is an event driven
system, so click event handlers will call the remote code and return
event handlers will do something with those values.

Button
1 Code
When Button 1 is
clicked, call the remote method "getStockPrice" and
pass the text in the first input box as an argument.
on (release)
{
ps.getStockPrice(box1.text);
}
|
Button 2 Code
When Button 2 is
clicked, call the remote method "getAllStockInfo"
and pass the text in the second input box as an argument.
on
(release)
{
ps.getAllStockInfo(box2.text);
} |
Button 3 Code
When
Button 3 is clicked, call the remote method "lookupSymbol" and
pass the text in the third input box as an argument.
on
(release)
{
ps.lookupSymbol(box3.text);
} |
Okay,
that's our Flash example! Here is the finished product below.
Perl
Client
Not
all of
you
out there use Flash, especially in the Free Software
community. The great thing about mod_perlservice is that everyone can
join the party. So lets, create a Perl Client that uses the same server
side stockmarket API.
use PService;
my $hostname =
"www.ivorycity.com";
my
$appname =
"stockmarket";
my $filename =
"quotes.pm";
my
$package =
"quotes";
#Create the
client
object
with following arguments:
#1) The host
you want
to use
#2) The
application
on the
host
#3) The perl
module
file
name
#4) The package
you
want to
use
my $ps = new
PSClient($hostname,$appname,$filename,$package);
# Just call
those
remote
methods and get the return value
my $price
=
$ps->getStockPrice("GE");
my
$info
=
$ps->getAllStockInfo("RHAT");
my $lookup =
$ps->lookupSymbol("Coca Cola");
#Share your
exciting
new
information with standard output
print "GE
Price:
".$price."\n";
print "Red Hat
Price:
".$info->{Price}."\n";
print "Red Hat
EPS:
".$info->{EarningsPerShare}."\n";
print "Coca
Cola's
ticker
symbol is ".$lookup."\n";
|
Using the PSClient object to call remote methods might feel
a little awkward since you'd expect to call them like quotes::getStockPrice()
,but think of the $ps instance as a proxy class to your remote
methods, if you like.
If things don't work, you can get errors by calling:
print $ps->get_errmsg();
Now, that's a local reserved function, it doesn't call the server.
It's one of a few reserved functions detailed in the
perl client reference.
As
you can see, it requires much less work to create an
example with the Perl client. You simply instantiate the PSClient
object, call the remote methods, and do something with the return
values. That's it. There is no protocol decoding, dealing with HTTP,
CGI arguments, or any of the old annoyances. Your remote code may as
well be local code.
Thanks For Taking Our Tour!
Well
that's mod_perlservice! I'm sure many of you developing
client-server applications can see the advantages of this system.
Personally, I've always found the existing technologies to be
inflexible and/or too cumbersome. The mod_perlservice system offers a
clean, simple, and scalable interface that unites client and server
side code in the most sensible way yet.
What's Next?
mod_parrotservice
Questions-Comments-Support
michaelcollins@ivorycity.com
Copyright © Ivory City Systems
2004.
You have permission to copy and
redistribute this document
so long as it retains this original copyright and trademark information.
The Seahorse Emblem is a Trademark
of Ivory City Systems.
|