Perl Server Pages (PSP) 0.5

PSPs add dynamic content to HTML using Perl as scripting language. It works very similar to ASP, JSP or PHP. We provide an easy to install package "myPSP". Features include custom taglibs, I18N, table support and logging.

Installation

Before you start, you need a webserver (e.g. Apache) with Perl (e.g. ActivePerl). These may be offered by your web space provider or run on your local PC.
You have downloaded an archive myPSP.zip.
  1. Unzip the content of myPSP.zip to the cgi-bin folder of your web server.
  2. Under Unix, make the file .../cgi-bin/psp/bin/psp.pl executable.
  3. Adjust the Shebang (the first line) of psp.pl. If it is #!/usr/bin/perl, your Perl interpreter is expected at c:\usr\bin\perl.exe in a Windows file system.
That is all, you can start the examples now. If you do not work locally, just replace the "localhost" in the URL by the name of the webserver.

Examples:
Bean Test Example demonstrating the use of a Perl bean.
Number Guesser 1 Little game originally written for JSP by Jason Hunter, demonstrating the use of PSP without servlet (model 1).
Number Guesser 2 The game again, demonstrating the use of PSP with servlet (model 2).

Tutorial

  1. Overview
  2. Syntax Summary
  3. Template Text (Static HTML)
  4. PSP Scripting Elements
  5. PSP Directives
  6. PSP Actions
  7. PSP Comments and Character Escaping Conventions

1. Overview

Like ASP, JSP, PHP or other, Perl Server Pages (PSP) let you separate the dynamic part of your pages from the static HTML. You simply write the regular HTML in the normal manner, using whatever Web-page-building tools you normally use. You then enclose the code for the dynamic parts in special tags, most of which start with "<%" and end with "%>". For example, here is a bit of a PSP that results in showing the actual host:
This is the actual host: <I><%= $ENV{'HTTP_HOST'} %></I>
You normally give your file a .psp extension, and install it in any place under your cgi-bin folder. Note that many web servers let you define aliases so that a URL that appears to reference an HTML file really points to a servlet or PSP page.

Aside from the regular HTML, there are three main types of PSP constructs that you embed in a page: scripting elements, directives, and actions. Scripting elements let you specify Perl code that will be executed, directives let you control the overall structure of the servlet, and actions let you specify existing components that should be used, and otherwise control the behavior of the PSP engine. To simplify the scripting elements, you have access to a number of predefined variables such as $request.

2. Syntax Summary

PSP Element Syntax Interpretation Notes
PSP Expression
<%= expression %>
Expression is evaluated and placed in output. Predefined variables are $request, $session and $root (available in scriptlets also).
PSP Scriptlet
<% code %>
Code is evaluated.  
PSP page Directive
<%@ page att="val" %>
Directions to the servlet engine about general setup. Legal attributes, with default values in bold, are:
  • contentType="MIME-Type"
PSP include Directive
<%@ include file="url" %>
A file on the local system to be included. The URL can be relative to the calling psp or absolute from the cgi-bin. Use the psp:include action to run the included file in a new web container.
PSP taglib Directive
<%@ taglib prefix="pref" tagdir="path" %>
Defines a tag library and prefix for the custom tags used in the PSP page. The path can be relative to the calling psp or absolute from the cgi-bin.
PSP Comment
<%-- comment --%>
Comment; ignored when PSP is translated. If you want a comment in the resultant HTML, use regular HTML comment syntax of <-- comment -->.
The psp:include Action
<psp:include page="URL">
 <psp:param name="user" value="jsmith"/>
</psp:include>
<psp:include servlet="URL"/>
Runs a file in an new web container and includes the result. The URL can be relative to the calling psp or absolute from the cgi-bin. Parameters must be forwarded to the new web container via the psp:param action. If you just want to include a file to the same context, use the page directive with the include attribute instead.
The psp:useBean Action <psp:useBean id="name" class="path"/> or
<psp:useBean id="name" class="path">
 <psp:setProperty att=val*/>
</psp:useBean>
Find or build a Perl Bean. The path can be relative to the calling psp or absolute from the cgi-bin.
The psp:setProperty Action
<psp:setProperty att=val*/>
Set bean properties, either explicitly or by designating that value comes from a request parameter. Legal attributes are
  • name="beanName"
  • property="propertyName|*"
  • param="parameterName"
  • value="val"
The psp:getProperty Action
<psp:getProperty
    name="beanName"
    property="propertyName"/>
Retrieve and output bean properties.  
The psp:forward Action
<psp:forward
    page="URL"/>
Forwards request to another page. The URL can be relative to the calling psp or absolute from the cgi-bin.

3. Template Text: Static HTML

In many cases, a large percent of your PSP just consists of static HTML, known as template text. In all respects except one, this HTML looks just like normal HTML, follows all the same syntax rules, and is simply "passed through" to the client. Not only does the HTML look normal, it can be created by whatever tools you already are using for building Web pages.

The one minor exception to the "template text is passed straight through" rule is that, if you want to have "<%" in the output, you need to put "<\%" in the template text.

4. PSP Scripting Elements

PSP scripting elements let you insert Perl code into the servlet that will be generated from the current PSP. There are two forms:
  1. Expressions of the form <%= expression %> that are evaluated and inserted into the output, and
  2. Scriptlets of the form <% code %> that are executed in the context of the PSP.
Each of these is described in more detail below.

4.1 PSP Expressions

A PSP expression is used to insert Perl values directly into the output. It has the following form:
<%= Perl Expression %>
The Perl expression is evaluated, converted to a string, and inserted in the page. This evaluation is performed at run-time (when the page is requested), and thus has full access to information about the request. For example, the following shows the host where the the page was requested:
This is the actual host: <I><%= $ENV{'HTTP_HOST'} %></I>
To simplify these expressions, there are a number of predefined variables that you can usesometimes called implicit objects. The available variables are request, response, out, session, application, config, pageContext, and page. Details for each are given below.
  • $request: The request lets you look at the request parameters (via getParameter).
  • $session: This is the Session object associated with the request. Recall that sessions are created automatically, so this variable is bound even if there was no incoming session reference.
  • $root:This is the path to the actual PSP, that can be used to e.g. include other PSPs.
Here's an example:
Your PSP: <%= $request->getParameter("page") %>

4.2 PSP Scriptlets

If you want to do something more complex than insert a simple expression, PSP scriptlets let you execute Perl code in the page context. Scriptlets have the following form:
<% Perl Code %>
Scriptlets have access to the same automatically defined variables as expressions. So, for example, if you want output the actual time you would do like this:
<% 
  $timenow = localtime(time());
  @timearray = split(/ +/,$timenow);
%>
The time is: <%= $timearray[2]." ".$timearray[1]." ".$timearray[4] %>
Note that code inside a scriptlet is not compiled to a servlet like e.g. in JSP. It is executed in the PSP context, which means that scriptlets need to contain complete Perl statements, and blocks left open will not work. For example, the following PSP fragment, containing mixed template text and scriptlets
<% if ($today eq "sunday") { %>
  You can sleep a little longer.
<% } else { %>
  Go to work!
<% } %>
will not work. Use custom tags instead:
<%@ taglib prefix="c" tagdir="/psp/lib/taglibs/custom" %>
<c:if condition="$today eq 'sunday'">
  You can sleep a little longer.
<c:else>
  Go to work!
</c:if>
If you want to use the characters "%>" inside a scriptlet, enter "%\>" instead.

5. PSP Directives

A PSP directive usually has the following form:
<%@ directive attribute="value" %>
However, you can also combine multiple attribute settings for a single directive, as follows:
<%@ directive attribute1="value1" 
              attribute2="value2"
              ...
              attributeN="valueN" %>
There are three main types of directive: page, which lets you define the content type, include, which lets you insert a file and taglib, which lets you define your own tags.

5.1 The PSP page Directive

The page directive lets you define one or more of the following case-sensitive attributes:
  • contentType="MIME-Type" or
    contentType="MIME-Type; charset=Character-Set"
    This specifies the MIME type of the output. The default is text/html. For example:
    <%@ page contentType="text/plain" %>

5.2 The PSP include Directive

This directive lets you include files. The directive looks like this:
<%@ include file="url" %>
The URL specified is normally interpreted relative to the PSP that refers to it, but you can tell the system to interpret the URL relative to the cgi-bin folder by starting the URL with a forward slash. The contents of the included file are parsed as regular PSP text, and thus can include static HTML, scripting elements, directives, and actions. Of course, the included file can also include files. Note that you can cause an endless loop by including files vice versa.

For example, many sites include a small navigation bar on each page. Due to problems with HTML frames, this is usually implemented by way of a small table across the top of the page or down the left-hand side, with the HTML repeated for each page in the site. The include directive is a natural way of doing this, saving the developers from the maintenance nightmare of actually copying the HTML into each separate file. Here's some representative code:

<HTML>
  <HEAD>...</HEAD>

  <BODY>
    <%@ include file="navbar.html" %>

    <!-- Part specific to this page ... -->

  </BODY>
</HTML>
Note that since the include directive inserts the files using the same web container, including file and included file operate on the same context, which means that the included file can access and change all parameters of the including file. If you want to hold the parameters apart, use the psp:include action instead. This runs the included file in a new web container as discussed in the tutorial section on PSP actions.

5.2 The PSP taglib Directive

This directive defines a tag library and a prefix for the custom tags used in the PSP page. The directive looks like this:
<%@ taglib prefix="pref" tagdir="path" %>
The path is interpreted relative to the PSP that refers to it, but you can tell the system to interpret the path relative to the cgi-bin folder by starting it with a forward slash. The path must lead to a folder containing Perl modules that inherit from the Tag class in the psp/lib folder. These modules take their parameters from the page context and use them to render HTML code or change other parameters in the page context.

Using the taglib directive gives you the chance to make your own taglib with your own tags.

6. Actions

PSP actions use constructs in XML syntax to control the behavior of the servlet engine. You can dynamically insert a file, reuse PerlBeans components or forward the user to another page. Available actions include:
  • psp:include - Include a file in a new web container. See Section 6.1.
  • psp:useBean - Find or instantiate a PerlBean. See Section 6.2 for an overview, and Section 6.3 for details.
  • psp:setProperty - Set the property of a PerlBean. See Section 6.4.
  • psp:getProperty - Insert the property of a PerlBean into the output. See Section 6.5.
  • psp:forward - Forward the requester to a new page. See Section 6.6.
These actions are described in more detail below. Remember that, as with XML in general, the element and attribute names are case sensitive.

6.1 The psp:include Action

This action lets you insert files into the page being generated. The syntax looks like this:
<psp:include page="URL">
 <psp:param name="user" value="jsmith"/>
</psp:include>
<psp:include servlet="URL"/>
Unlike the include directive, which inserts the file to the same web container, this action runs the file in its own web container. This has the advantage that parameter changes in the included file do not affect parameters of the including file. On the other hand parameters must be explicitly handed over from the included to the including file using the psp:param tag. For example, here is a PSP that inserts four times the same snippet into an "Employees List" Web page. Each time the snippet renders an employee, taking the id from the parameter tag.

employees.psp

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>List of Employees</TITLE>
</HEAD>

<BODY>

Here is a list of employees:
<OL>
  <LI><psp:include page="employer.psp"><psp:param name="id" value="dsmith"/></psp:include>
  <LI><psp:include page="employer.psp"><psp:param name="id" value="pgarfield"/></psp:include>
  <LI><psp:include page="employer.psp"><psp:param name="id" value="jwood"/></psp:include>
</OL>
</BODY>
</HTML>

6.2 The psp:useBean Action

This action lets you load in a PerlBean to be used in the PSP. The simplest syntax for specifying that a bean should be used is:
<psp:useBean id="name" class="path"/>
This usually means "instantiate an object of the class specified by class, and bind it to a variable with the name specified by id." Now, once you have a bean, you can modify its properties via psp:setProperty, or by using a scriptlet and calling a method explicitly on the object with the variable name specified earlier via the id attribute. Recall that with beans, when you say "this bean has a property of typeX called foo", you really mean "this class has a method called getFoo that returns something of type X, and another method called setFoo that takes an X as an argument." The psp:setProperty action is discussed in more detail in the next section, but for now note that you can either supply an explicit value, give a param attribute to say that the value is derived from the named request parameter, or just list the property to indicate that the value should be derived from the request parameter with the same name as the property. You read existing properties in a PSP expression or scriptlet by calling the appropriate getXxx method, or more commonly, by using the psp:getProperty action.

The path specified is normally interpreted relative to the PSP that refers to it, but you can tell the system to interpret the path relative to the cgi-bin folder by starting the URL with a forward slash.

Here is a very simple example that loads a bean and sets/gets a simple String parameter. You can test the example on your local server:

BeanTest.psp

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Reusing PerlBeans in PSP</TITLE>
</HEAD>

<BODY>

<psp:useBean id="test" class="SimpleBean"/>
<psp:setProperty name="test" property="message" value="Hello WWW"/>
             
<H1>Message: <I>
<psp:getProperty name="test" property="message"/>
</I></H1>
             
</BODY>
</HTML>

SimpleBean.pm

Here's the source code for the bean used in the BeanTest PSP.
package SimpleBean;
use Servlet;
@ISA = qw(Servlet);

sub setMessage($$) {
  my ($self, $value) = @_;
  $self->{_message} = $value;
}

sub getMessage($) {
  my ($self) = @_;
  return (not defined $self->{_message})? "No message specified" : $self->{_message};
}
1;

Typical result:

Message: Hello WWW

6.3 The psp:setProperty Action

You use psp:setProperty to give values to properties of beans that have been referenced earlier. You can do this in two contexts. First, you can use psp:setProperty after, but outside of, a psp:useBean element, as below:
<psp:useBean id="myName" ... />
...
<psp:setProperty name="myName" property="someProperty" ... />
In this case, the psp:setProperty is executed regardless of whether a new bean was instantiated or not. A second context in which psp:setProperty can appear is inside the body of a psp:useBean element, as below:
<psp:useBean id="myName" ... >
  ...
  <psp:setProperty name="myName" property="someProperty" ... />
  ...
</psp:useBean>
Here, the psp:setProperty is executed only if a new object was instantiated.

There are four possible attributes of psp:setProperty:

Attribute Usage
name This required attribute designates the bean whose property will be set. The psp:useBean element must appear before the psp:setProperty element.
property This required attribute indicates the property you want to set. However, there is one special case: a value of "*" means that all request parameters whose names match bean property names will be passed to the appropriate setter methods.
value This optional attribute specifies the value for the property. You can't use both value and param, but it is permissible to use neither. See the discussion of param below.
param This optional attribute designates the request parameter from which the property should be derived. If the current request has no such parameter, nothing is done: the system does not pass null to the setter method of the property. Thus, you can let the bean itself supply default values, overriding them only when the request parameters say to do so. For example, the following snippet says "set the numberOfItems property to whatever the value of the numItems request parameter is, if there is such a request parameter. Otherwise don't do anything."
<psp:setProperty name="orderBean"
                 property="numberOfItems"
                 param="numItems" />
If you omit both value and param, it is the same as if you supplied a param name that matches the property name. You can take this idea of automatically using the request property whose name matches the property one step further by supplying a property name of "*" and omitting both value and param. In this case, the server iterates through available properties and request parameters, matching up ones with identical names.

6.4 The psp:getProperty Action

This element retrieves the value of a bean property, converts it to a string, and inserts it into the output. The two required attributes are name, the name of a bean previously referenced via psp:useBean, and property, the property whose value should be inserted. Here's an example; for more examples, see Sections 6.2.
<psp:useBean id="itemBean" ... />
...
<UL>
  <LI>Number of items: 
      <psp:getProperty name="itemBean" property="numItems" />
  <LI>Cost of each:
      <psp:getProperty name="itemBean" property="unitCost" />
</UL>

6.5 The psp:forward Action

This action lets you forward the request to another page. It has a single attribute, page, which should consist of a relative URL. This could be a static value, or could be computed at request time, as in the two examples below.
<psp:forward page="/utils/errorReporter.psp" />
<psp:forward page="<%= somePerlExpression %>" />

7. Comments and Character Quoting Conventions

There are a small number of special constructs you can use in various cases to insert comments or characters that would otherwise be treated specially. Here's a summary:
Syntax Purpose
<%-- comment --%>
A PSP comment. Ignored by PSP-to-scriptlet translator. Any embedded PSP scripting elements, directives, or actions are ignored.
<!-- comment -->
An HTML comment. Passed through to resultant HTML. Any embedded PSP scripting elements, directives, or actions are executed normally.
<\%
Used in template text (static HTML) where you really want "<%".
%\>
Used in scripting elements where you really want "%>".
\'
A single quote in an attribute that uses single quotes. Remember, however, that you can use either single or double quotes, and the other type of quote will then be a regular character.
\"
A double quote in an attribute that uses double quotes. Remember, however, that you can use either single or double quotes, and the other type of quote will then be a regular character.
%\>
%> in an attribute.
<\%
<% in an attribute.