Dylan Server Pages Documentation

Contents

  1. Overview
  2. DSP Content Authoring
    1. Overview (file names, exporting, format, passing tag args, ...)
    2. DSP Directives
    3. The "dsp" Tag Library
  3. DSP Programming
    1. Overview (pointer to Koala doc for sessions, exporting, query args, requests, responses, page life cycle, etc)
    2. Page Classes
    3. Tag Libraries
    4. Tags
    5. Handling HTTP Methods (GET, POST, HEAD)
    6. Forwarding/Redirecting Requests
    7. Named Methods
  4. DSP Technical Reference

Overview of DSP

Dylan Server Pages (DSP) is a template engine for providing dynamic web site content using the Dylan language. They are similar in spirit to JavaServer Pages, but without the ability to mix program logic and page content, which is a bad idea anyway. All dynamic content is invoked via DSP tag calls such as <xx:show-current-username/>.

(Okay, opinions can vary on the wisdom of closly mixing content and implementation, as with JSP scriptlets, but I contend that it's only ok for one-off hacks and small one-person projects. This isn't necessary in DSP because with Dylan's powerful language features writing custom tags is trivial and concise compared to JSP. And with Open Dylan, you often don't even need to restart your application to compile new custom tags and try them out.)

Currently, a DSP application is implemented as a Dylan project that uses the Koala HTTP server library. This effectively means that each DSP application has to run on a different Koala server and therefore on a different HTTP port. (The plan is to eventually fix Koala to load DSP application libraries at runtime, based on configuration files.)

Content Authoring

Authoring Overview

DSP templates contain normal HTML plus DSP tag calls. DSP tag calls generate the dynamic content of you web pages. They use standard XML syntax. For example, <mylib:mytag arg="foo"/> is tag call with no body that passes one argument, arg, to mytag when it is invoked. "mylib" tells the DSP template engine what tag library (taglib for short) "mytag" will be found in.

There are several special tags called directives defined that couldn't easily have been defined by the user. DSP directives use the same syntax as other tags, but they use the special tag library name %dsp. For example, the include directive might look like this: <%dsp:include location="foo.dsp"/>.

Each top-level template file must have a corresponding instance of <dylan-server-page> associated with it. This is accomplished with the define page macro, which also publishes the URLs associated with the page.

DSP template files may have any filename extension, but the extension ".dsp" may be treated specially in the future. For example, .dsp files may eventually be automatically exported as <dylan-server-page>s.

DSP Directives

A DSP directive is used much like a normal DSP tag, but it couldn't be written as a normal tag without special support from the DSP engine. DSP directives are distinguished by the %dsp tag prefix. There are two built in DSP directives:

%dsp:include
Includes another DSP template (or plain HTML file) in the current page. Example usage:
<%dsp:include location="header.dsp"/>
Note that if the location given is absolute (i.e., begins with a slash) then the document is looked up relative to the document root directory. Otherwise it is looked up relative to the directory containing the current document.

%dsp:taglib
Declares another tag library to be in effect for the remainder of the page. Taglib directives are cumulative. That is, using two or more %dsp:taglib directives on the same page means that tags in either taglib may be used on that page. Example usage:
      <%dsp:taglib name="my-taglib" prefix="xx"/>
      ...
      <xx:my-tag/>
      ...
    
The value of the name argument must be the same as the name in a define taglib form. The prefix may contain any characters except for < and : and may not be "%dsp".

The "dsp" Tag Library

The "dsp" taglib defines a few tags that are generally useful for any web application.
dsp:if
Conditionally includes its body content if a predicate returns true. Example usage:
      <dsp:if test="my-predicate?">
        <dsp:then>...true part...</dsp:then>
        <dsp:else>...false part...</dsp:else>
      </dsp:if>
    
Note that there may be multiple dsp:then and dsp:else tags inside the same dsp:if tag body. If there is any plain HTML in the body of the dsp:if, and outside of any dsp:then or dsp:else tags, it will always be displayed.

dsp:then
Executes its body only if the test predicate of the containing dsp:if tag returned true. When not contained in the body of a dsp:if tag its body will not be executed.

dsp:else
Executes its body only if the test predicate of the containing dsp:if tag returned false. When not contained in the body of a dsp:if tag its body will not be executed.

dsp:table
TBD. Haven't quite settled on a design here yet.

dsp:table-row-number
Displays the one-based number of the row currently being displayed.

DSP Programming

Tag Libraries

Tags can be organized into separate tag libraries if needed (e.g., for large web apps). Each DSP page may use the %dsp:taglib directive to specify which tag libraries are active for that page. The built-in "dsp" tag library is automatically available to all DSP pages, without having to use the %dsp:taglib directive to make it active. The "dsp" taglib includes some tags that are useful for almost all web pages.

Taglibs are fairly uninteresting as far as programming a DSP application goes. They are only used when defining tags and named methods, to specify which taglib those objects belongs to. They are defined as follows:

  define taglib demo ()
  end;
  
The above defines a taglib named "demo". See the Tags section for how the taglib is specified when defining a tag. This taglib would be included in a page with the following directive:
<%dsp:taglib name="demo" prefix="xyz"/>
and its tags would then be used like this:
<xyz:tag-one/>
Note that prefix is optional, and defaults to the value of name.

Tags

Tags are defined with the "define tag" macro. The syntax is:
    define [body] tag tag-name [in taglib-name]
        (method-parameters)
        (tag-parameters)
      ...code...
    end;
  
The following example tag should clear things up a bit:
    define tag current-time in demo
        (page :: <dylan-server-page>)
        (style)
      write(output-stream(current-response()), current-time(style));
    end;
  
The above defines a tag called "current-time" in the "demo" taglib which outputs the current time in the DSP page. See the define tag macro for a full description tag definition. The above tag would be called like this:
    <%dsp:taglib name="demo" prefix="xyz"/>
    <xyz:current-time style="24hr"/>
  
Note that style defines a parameter for the tag call such that the style variable is bound to the value of that parameter in the body of the tag definition.

The tag functon must always accept one argument: page, an instance of <dylan-server-page>.

DSP Technical Reference

define taglib Macro Library: koala; Module: http-server

Signature

define taglib taglib-name ()
end
Summary
Defines a new tag library with name taglib-name.

define tag Macro Library: koala; Module: http-server

Signature

define [modifiers] tag tag-name [in taglib-name]
    (method-parameters)
    (tag-call-parameters)
  body
end
Summary
Defines a new tag named tag-name in the taglib-name tag library.
Arguments
modifiers
  The only valid modifier is body, which must be used if the tag allows nested body elements. If body is not specified then the tag call must end in "/>" or an error will be signalled when the DSP template is parsed. If body is specified, method-parameters must have a third parameter (see below).

tag-name
  The name of the tag, as it will appear in the .dsp file.

taglib-name
  The name of the taglib the tag should be added to.

method-parameters
  Each tag definition creates a method that will be called when the tag is invoked. This is the parameter list for that method. The basic form of the parameter list is (page[, process-body]). page is an instance of <dylan-server-page>. process-body is an instance of <function>. The process-body argument should be specified if and only if the body modifier is supplied.

tag-call-parameters
  tag-call-parameters allows you to receive named keyword arguments from a tag call. For example, if your tag call looks like
<xx:foo arg1="one" arg2="2">
then tag-call-parameters might look like
(arg1, arg2)
in which case body code may refer to arg1 and arg2. If the tag call doesn't specify a given tag-call-parameter then #f will be used. If a tag-call-parameter has a type specifier, then the passed argument will be parsed into the appropriate type before it is passed. See the parse-tag-arg generic function. Note that this means specifying a type of which #f is not a member effectively makes the tag-call-parameter required. For example,
(arg1, arg2 :: <integer>)
specifies that arg1 is optional (it will be a <string> if supplied) and arg2 is required and must be parsable to an <integer>.

body
  The body of the tag definition. method-parameter and tag-call-parameters are bound within the body.

Description
Defines a new tag named tag-name in the taglib-name tag library. For simple DSP tags with no body elements, the body code normally just does output to the output stream of the current response, generating dynamic output in place of the literal tag call in the source file. Tags that have body elements may additionally want to setup state for nested tags to use. This may be done, for example, through the use of dynamically bound thread variables or storing information in the session or page context.

When the DSP engine invokes the tag to generate dynamic content it passes arguments that match method-parameters. tag-call-parameters receive arguments specified in the tag call, in the DSP source file, after they have been parsed to the specified types.

Examples
A simple tag in the "demo" taglib that displays "Hello, world!" in the page. It is invoked with <demo:hello/>:
    define tag hello in demo
        (page :: <dylan-server-page>)
        ()
      format(output-stream(current-response()), "Hello, world!");
    end;
  
A tag that allows body elements, and processes the body elements three times. It is invoked with <demo:three-times>...whatever...</demo:three-times>:
    define body tag three-times in demo
        (page :: <dylan-server-page>,
         do-body :: <function>)
        ()
      for (i from 1 to 3)
        do-body();
      end;
    end;
  
See Also
define taglib, <dylan-server-page>, <response>, output-stream, map-tag-call-arguments, show-tag-call-arguments