Team LiB   Previous Section   Next Section

6.1 Embperl

Gerald Richter's Embperl program is a popular solution for those who want to separate web page design from data coding issues while taking advantage of Perl's ability to generate dynamic content without having to worry about web page design issues. As its name suggests, Embperl provides the ability to embed Perl within your HTML presentation layer templates.[1]

[1] This approach is similar to what is done with PHP (http://www.php.net) and PL/SQL Server Pages (PSPs).

The Embperl 2.0 release promises extensive new capabilities, offering such features as XML and XSLT integration. Although Embperl is implemented primarily in Perl, it also has a C back end for speedier processing. For detailed information, go to:[2]

[2] As a rule of thumb, only the latest stable releases make it to CPAN, whereas beta versions are generally available on the other site.

http://perl.apache.org/embperl
http://www.cpan.org/authors/id/GRICHTER

In the following sections we'll describe how to install Embperl on Unix and Win32 systems. The Apache configuration and execution of Embperl is virtually identical on the two systems, so once we're installed on both systems we'll run through a single configuration sequence.

6.1.1 Installing Embperl on Unix

This section describes how to install Embperl and its associated modules on Unix platforms.

Although you can use Embperl under vanilla CGI Apache, we strongly recommend that you use mod_perl. Not only is the performance difference astonishing, but mod_perl also allows you to use a wide range of Apache modules, including the highly useful Apache::Session and Apache::DBI. And without Apache::Session (as we describe below), you will get no session persistence between HTTP requests.

  1. If you're installing Embperl on Unix, you need to obtain a few additional modules to get its full application benefit. (Embperl is also expecting you to have pre-loaded mod_perl, which provides it with many of its extended options. We'll also assume this, for the rest of this installation.)

    Storable.pm

    Raphael Manfredi's popular advanced module for storing various persistent data structures in Perl (and required by Apache::Session). In the later section, Section 6.1.5, we'll explain the advantages of storing persistent web data. Download and install the tarball from the following Perl 5 Porters site:

    http://www.cpan.org/authors/id/A/AM/AMS

    Apache::Session

    Jeffrey Baker's Apache Perl module. This interface between Apache and the Storable.pm module is used to store persistent web data. Download and install it from:

    http://www.cpan.org/authors/id/JBAKER

    Apache::SessionX

    This is a subsidiary module developed by Gerald Richter to complement Embperl by creating an extended persistence framework for Embperl's session data between HTTP requests (thus extending Apache::Session). Download and install the latest version from the CPAN site at:

    http://www.cpan.org/authors/id/GRICHTER

  2. For testing purposes, Embperl also requires that LWP and all of its precursor modules be installed; Chapter 5, contains the full details about LWP installation.

  3. Once you've installed these required modules, you can install Embperl itself. During the installation you need to supply the location of your Apache source directory. Embperl can then get hold of the relevant Apache code headers, and configure itself against mod_perl. For example:

    $ perl Makefile.PL
    Build with support for Apache mod_perl?(y/n) [y]y
    Use ../apache_1.3.24/src as Apache source(y/n) [y]y
    ...
  4. Once Embperl has been configured, complete the installation as follows:

    $ make
    $ make test
    $ make install

    We can now head on down to Embperl's configuration.

6.1.2 Installing Embperl on Win32

Installing Embperl on Win32 is remarkably easy because of the good work of those physics philosopher-kings at the University of Winnipeg. The gig's all been tied up with super-strings and made as simple as falling off a p-brane bubble quark. When it's installing, take a look at all of those modules you get. It's just like Christmas:

PPM> set repository theoryx5 
     http://theoryx5.uwinnipeg.ca/cgi-bin/ppmserver.pl?urn:/PPMServer
PPM> set save
PPM> install Storable
Install package 'Storable?' (y/N): y
Installing package 'Storable'...
...
PPM> install Apache-Session
Install package 'Apache-Session?' (y/N): y
Installing package 'Apache-Session'...
...
PPM> install Apache-SessionX
Install package 'Apache-SessionX?' (y/N): y
Installing package 'Apache-SessionX'...
...
PPM> install Embperl
Install package 'Embperl?' (y/N): y
Installing package 'Embperl'...
...
PPM> quit

And that's it. We're now ready to configure and deploy Embperl, a process that is virtually identical on both Win32 and Unix.

6.1.3 Deploying HTML::Embperl

There are many different ways to deploy Embperl, and all of them are discussed in depth within the documentation. For starters, take a look at the information obtained from the following command:

$ perldoc Embperl

Our favorite way of deploying Embperl is to ask the Apache web server to call it. Apache can be called with any files bearing a particular suffix (such as .epl) in the same way that you can configure Apache to call Perl if it finds scripts ending with .cgi. You do this in httpd.conf by adding a handler (in our case a PerlHandler) and associating a file type with a nominated suffix in the following way. Here we have chosen the typically generic Embperl .epl suffix:

PerlModule Embperl
EMBPERL_DEBUG 2285
<Files *.epl>
   SetHandler  perl-script
   PerlHandler Embperl
   Options     ExecCGI
</files>
  
AddType text/html .epl
  1. Once we restart Apache, every time anybody calls up a web page from this server, suffixed with .epl, Embperl will be called to deal with it.

  2. There are many different EMBPERL_DEBUG levels, and we've chosen an output level initially recommended by the Embperl download installation files. While you're getting used to Embperl, you may want to try these settings as a starting point, and then alter them to create varying output within Apache's generated logs as you progress.

    We started, as illustrated in Example 6-1, with our first Embperl .epl file, which checks up on who is accessing which object within the Oracle database. A bit later we'll run through how Embperl interprets this information.

    Example 6-1. ObjectAccess.epl — Embperl and Oracle
    <html><head>
    <title>Embperl Object Access Checker</title>
    </head><body><center>
      
    <h1>Hello Embperl, Let's Check Object Access! 8-)</h1><hr>
      
    [-
      
    $url = 'dbi:Oracle:orcl';
    $user = 'system';
    $passwd = 'manager';
      
    use DBI ;
      
    # Connect to the database
    $dbh = DBI->connect($url, $user, $passwd, {RaiseError=>1});
      
    # Prepare the SQL to check up on object access
    $sth = $dbh->prepare ('select s.osuser "OS User", ' .
                          's.username "Username", ' .
                          's.serial# "Serial#", ' .
                          's.sid "Sid", ' .
                          'a.owner||\'.\'||a.object "Object Name", ' .
                          '\'=> \'||a.type "Lock Mode" ' .
                          'from v$session s, v$access a ' . 
                          'where a.sid = s.sid ' .
                          'order by 6,1,2,3,4,5');
    # Execute the Query
    $sth->execute;
      
    # Get the Column Headers
    $head = $sth->{NAME} ;
    # Fetch the data into the drillable data_ref array reference
    $data_ref = $sth->fetchall_arrayref ;
    -]
      
    <table border="2">
    <tr><th>[+ $head->[$col] +]</th></tr>
    <tr><td>[+ $data_ref->[$row][$col] +]</td></tr>
    </table>
    <hr></center></body></html>

    Store ObjectAccess.epl within the ../htdocs directory alongside ordinary flat HTML files, and then fire up Apache. Our new Embperl file produced the subsequent browser output in Figure 6-1. So that's the culprit!

Figure 6-1. Our first Embperl execution
figs/pdba_0601.gif

6.1.4 Looking at Embperl Syntax

Now let's look at what is going on in Example 6-1. There are three main ways to actually embed Perl within Embperl templates; these different approaches are summarized in Table 6-1. In the following sections we'll focus on how Embperl syntax differs from standard Perl syntax.

Table 6-1. Embedding Perl within the Embperl template

Format

Description

Example

[- ... -]

Code execution: The code between the [- and the -] is executed, without any HTML being generated. This approach is mainly for assignments, function calls, creating database connections, and so on, as in Example 6-1.

[-

$dbh = DBI->connect(

$url, $user, $passwd)

-]

[+ ... +]

Code output: The code is executed as with the previous example, except this time the last thing evaluated is streamed back to the HTML output.

<tr><th>

[+ $head->[$col] +]

</th></tr>

[! ... !]

One-time execution: The code is executed as with [- ... -], but only for the first request, which is useful for variable or subroutine initialization and other one-off executions

[!

Sub session_start {

$start_time = localtime; }

!]

6.1.4.1 Controlling template-driven program flow

To exercise structured program flow within Embperl, you can employ another square-bracketed syntactical element:

[$ <conditional element> <optional conditional construct> $]

This is perhaps best explained by working through the examples in the following numbered list:

  1. Suppose you want to set up a conditional if chain to do different things with HTML. Depending upon how you're being sent data, you do it like this:

    [$ if $ENV{REQUEST_METHOD} eq 'GET' $]
        <h2> I see you've called me with a GET request! :-) </h2>
    [$ elsif $ENV{REQUEST_METHOD} eq 'POST' $]
        <h2> Thanks for calling me with a POST request! 8-) </h2>
    [$ else $]
       <h1> You've created a new Request Method, Congratulations! $-) </h1>
    [$ endif $]

    Notice that although this code looks similar to ordinary Perl, brackets such as (...), are missing from the main if condition, and no curly brackets like {...} are used to wrap statements. Also notice that whereas in ordinary Perl you would use a left-facing bracket, }, to end the complete if statement, in Embperl you use endif instead. This is a keyword that traditional Perl would fail to recognize.

    We have been told that Embperl 2.0 will be more closely aligned with standard Perl.

  2. You can also use while loops, for example, to display the Apache server's current environment:

    [$ while ($env_variable_name, $env_value) = each (%ENV) $]
       [+ $env_variable_name +] = [+ $env_value +] <br>
    [$ endwhile $]

    Again notice the use of endwhile rather than a left-facing curly bracket, }.

  3. Similarly, you can also employ do...until loops:

    [- 
    @crew = ('Kirk', 'McCoy', 'Spock', 'Beam Me Up'); 
    $tribble = 0;
    -]
    [$ do $]
       [+ $crew[ $tribble++ ] +]
    [$ until $tribble > $#crew $]

    Notice how the tribbles keep growing in number.

  4. You can also use foreach loops:

    [-
    $warp_factor = 1;
    @federation_planet = ('Earth', 'Vulcan', 
                          'Solaria', 'Aurora', 'Terminus', 'Trantor');
    -]
    [$ foreach $thataway ( @federation_planet ) $]
    Head for Federation Planet [+ $thataway +], 
       Mr Sulu, Warp Factor [+ $warp_factor++ +]
    [$ endforeach $]
6.1.4.2 Strict variable naming

As with standard Perl, variables pop into existence as soon as you mention them, but if you'd rather enforce stricter discipline and pre-declare global variable names, you can use var:

[$ var $klingon @vulcan %romulan $]

This is equivalent to the Perl strict pragma shown here:

use strict;
use vars qw ($klingon @vulcan %romulan) ;
6.1.4.3 Useful table tricks

The eagle-eyed among you may have spotted something strange about the following lines in Example 6-1:

<tr><th>[+ $head->[$col] +]</th></tr>
<tr><td>[+ $data_ref->[$row][$col] +]</td></tr>

There is only one table header element, and one detail element, yet the screen in Figure 6-1 is filled to overflowing with the milk and honey of multiline and multicolumn results. What's going on? A little bit of magic.

First, the special $col variable works out just how many element are within the array referenced by $head, which was created by the $head = $sth->{NAME} code line. The special $row variable does exactly the same for the $data_ref reference value.

Next, Embperl iterates through the whole of the arrays accessed by these variables, until $col and $row return undef values (i.e., they run out of milk and honey). You may want to avoid questioning too much how Embperl does this; otherwise the fairy dust may lose its sparkle. The Pandora's box of source code is available though, if you're prepared to open it.

6.1.5 Embperl Forms Handling and Apache::Session

One of the major benefits of the Web is its stateless protocol, HTTP, which makes your processing extremely lightweight at both the server and browser ends. Unfortunately, the stateless protocol can also be a great disadvantage when compared with a stateful client-server model, for example. The problem is that you keep losing all of your user information every time users change pages. This can be financially challenging if your site runs shopping-cart applications!

Embperl can perform many of the regular <hidden> type shenanigans to overcome this limitation, but it can also make use of Apache::Session to draw an Excalibur sword of stateful data from a dry stone of statelessness. It stores this rich vein of information between page requests via the following special Perl hash variables:

%udat

Stores individual user data. Every time an individual comes back to your server, via his browser, to hit different pages, you can access all of his previously input data (if your Embperl script stored it neatly away when you last had access to it).

%mdat

Stores data for a nominated module or page.

%fdat

Stores all of the data associated with a form.

%idat

Stores all of the data input so far on a particular form, which is very useful for those of us who relish sticky widgets.

    Team LiB   Previous Section   Next Section