Python Server Pages

The motivation for Python Server pages comes from the Jakarta Server Pages (formerly JavaServer Pages and referred to as JSP) based on standard Java technology that was designed at the end of the past century.   The JSP technology was adopted and refined by a large community of developers, organizations, and commercial businesses.  

Here is a link to more information about Jakarta Server Pages:   http://en.wikipedia.org/wiki/Jakarta_Server_Pages

Python Server Pages (PSP) are HTML pages that contain elements that reference PSP directives, PSP tags, or embedded python code.   PSPs are compiled by a PSP compiler, to produce a servlet, which is then executed by the \npython servlet container.   If the python servlet container finds a servlet from a previous successful compilation, and if the PSP has not changed since the servlet was previoualy compiled, the container does not need to compile the PSP again, the container simply executes the servlet.  

This page was generated from a Python Server Page (PSP). 

filename.css
      this is a code example

Including Python Code into a PSP

The strings <% and %> are used to introduce and delineate blocks of python code within a PSP.   If it is necessary to include these delineation strings as HTML, the strings must be escaped using the following sequences: <\% and %\>   

An Exciting Example

The following fragments provide one example for integrating a sample of python code into a PSP.   The example consists of a PSP declaration for some code that will provide a service that can be executed from other fragments within the PSP:

    <%! def cube(self, n:int) -> int:
        return n*n*n %>

The following block of HTML demonstrates how to use this new code declaration:


    <%= "The cube of 3 is: "+str(self.cube(3)) %/>

and here's how the fragments above can be combined to create a complete example:

cube.psp
code not included yet

The result:   The cube of 3 is: 27

PSP Directives

Content Type

The content type directive is a convenient place to specify the content type of the returned page.

    <%@ page contentType="text/html" %>

Note that the content type directive acts as a place holder to hold a value for the HTTP response that the servlet will produce.   By default, the content type will be set to "text/html" based on the assumption that PSPs are most often used to create HTML output.   PSPs that produce JSON output will likely want to set the content type to "application/json".  

Static Include

The static include directive tells the PSP compiler to read the contents of the specified file and as input for the current page. 

  <%@ include file="relative filename" %>
Note that the file referenced by the include directive is read once, when the PSP is compiled.  While this may offer a marginal performance benefit, if the contents of the file to be included is changed after the PSP has been compiled, these later changes will not be seen by the PSP compiler and will not be reflected in the PSP output.  

Consider using the PSP Include Tag to include the contents of another PSP into a PSP, so that the PSP compiler will check modification dates and recompile when necessary.

Fragment 1
This is fragment 1

Custom Tag Library Declarations

The following page directive declares a custom tag library:

  <%@ taglib uri="WEB-INF/MyTaglib.tld" prefix="something" %>
Best practices suggest that tag lib declarations belong at the top of a PSP page; however, the PSP compiler only requires them to be declared prior to being used.   Also, it is a best practice to place tag lib declaration files somewhere out of reach of browsers and applications that invoke the PSP page.   Placing them somewhere under "WEB-INF" protects them from direct access by an HTTP request.  

Using PSP Action Tags

The PSP compiler introduces tags which make new features available to a PSP designer.   These tags can be easily recognized from HTML constructs through the use of the "psp" prefix.    For compatibility with older Java technologies, this PSP compiler accepts a prefix of either "psp" or "jsp" for specifying PSP tags.  

Including PSPs

Designers will frequently want to take advantage of common constructs by placing them in files which can be included into one of many PSP pages.   The following tag demonstrates how one PSP can include another page:

    <psp:include page="fragment1.psp" />
An an example, if the file to be included (fragment1.psp) contains the following content:
fragment1.psp
    <b>Fragment 1</b><br>
    This is fragment 1
    <p>
the result of using include tag above will produce the following output:

Fragment 1
This is fragment 1

Included PSPs are independent from the PSP that included it, they are compiled independently and they do not inherit taglib declarations.  

Using Custom Tag Libraries

Once a custom taglib has been declared, it can be referenced using its prefix. Note that tags can be used in either a short form or a long form.

When the PSP compiler encounters a reference to a tag in a PSP, it uses the tag's prefix and name to locate the tag within the taglib descriptor file.   The compiler can then use information from the taglib descriptor to generate the python code necessary to invoke a python class that is to be used to implement the service of the tag.  

Tags are defined using XML within a taglib descriptor file.   (see elsewhere for a description of the contents of a taglib descriptor file)

Empty tags

An empty tag is a tag that takes no parameters and has no content:

  <something:HelloTag/>
By way of example, suppose the tag entry in the taglib specified by the tag above specified that the implementation for this tag is found in the following file (HelloTag.py):
HelloTag.py
    from pythonx.servlet.psp.tagext.SimpleTagSupport import SimpleTagSupport

    class HelloTag(SimpleTagSupport):
        self.getPspContext().getOut().println("Hello Custom Tag!")
The tag will produce the following output when incorporated into a PSP:   Hello Custom Tag!

Tags with parameters

A tag can be specified with zero or more named parameters, where each parameter will be used to initialize an instance variable representing the tag.   The parameter's name will be used as the name of the instance variable that will be initialized with the value of the parameter.  
  <something:MessageTag message="I'm a lumberjack and I'm OK."/>
produces the following:   I'm a lumberjack and I'm OK.

Note: The PSP compiler automatically translates all parameter names to lower case.

Tags with content

The following text (note the embedded tag within the content):

  <something:ContentTag>
  This is the <something:HelloTag/> for this tag
  </something:ContentTag>
will produce the following output:   This is the Hello Custom Tag! for this tag