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.
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 .
- Unzip the content of
myPSP.zip to the cgi-bin folder of your web server.
- Under Unix, make the file
.../cgi-bin/psp/bin/psp.pl executable.
- 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). |
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 .
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:
|
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.
|
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.
PSP scripting elements let you insert Perl code into the servlet
that will be generated from the current PSP. There are
two forms:
- Expressions of the form
<%= expression %>
that are evaluated and inserted into the output, and
- 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.
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" %>
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.
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.
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.
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>
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
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.
|
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>
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 %>" />
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.
|
|