Pustefix Reference Documentation

Jens T. Lautenbacher

Martin Leidig

Sebastian Marsching

Stephan Schmidt


Table of Contents

Introduction
1. Installation
1.1. Requirements
1.2. Prepare the project directory
1.3. Unpack the skeleton
1.4. Configure Eclipse
1.5. Build parameters & first build
2. Architecture
2.1. High Level View
2.2. The Pustefix backend system
2.3. Recursive XSL Transformations
2.3.1. XSL Targets
3. Configuring Pustefix
3.1. Overview
3.2. Configuration File Format
3.2.1. Java Property Files
3.2.2. Configuration Fragments
3.3. Project configuration
3.3.1. The site wide configuration servletconf/projects.xml.in
3.3.2. Servlet filter configuration
3.4. Servlet configuration
3.4.1. ContextXMLServlet configuration format
3.4.2. DirectOutputServlet
3.5. Page Configuration (depend.xml)
3.5.1. Structure of the depend.xml
3.5.2. The <make/> tag
3.5.3. The <page/> tag
3.5.4. Target definition
3.5.5. Standard page definition
3.5.6. Standard master target definition
3.5.7. Standard metatags target definition
3.6. Misc configuration
3.6.1. FactoryInitServlet (factory.xml)
3.6.2. Global properties (pustefix.xml)
3.6.3. web.xml
4. Core Pustefix tag library
4.1. Defining the structure of a document
4.1.1. Structure of a Type 1 document
4.1.2. Structure of a Type 2 document
4.2. Creating links to internal and external pages
4.2.1. pfx:button
4.2.2. pfx:url
4.2.3. pfx:elink
4.3. Including text and images
4.3.1. Include parts (<pfx:include>)
4.3.2. Generated include requests (<pfx:maincontent>)
4.3.3. Displaying images (<pfx:image>)
4.4. Handling HTML forms
4.4.1. Form creation
4.4.2. Submitting forms
4.4.3. Arguments, comands and anchors
4.4.4. Form elements
4.4.5. Handling error conditions
4.4.6. Avoiding duplicate form submission
4.5. Miscellaneous utility tags
4.5.1. Checking page status
4.5.2. Displaying content based on the language
4.5.3. Displaying content based on the theme
4.5.4. Using the Pustefix console
5. Important Concepts
5.1. Servlets
5.1.1. Servlets provided by the core framework
5.2. Processing of Requests
5.2.1. The Context
5.2.2. PageFlow
5.2.3. States
5.2.4. Influencing the page request cycle
5.2.5. The basic Pustefix Request Cycle
5.2.6. Pustefix State implementations
5.2.7. Pustefix PageFlow implementation: DataDrivenPageFlow
5.3. The data model: Context resources
5.4. Wrappers and Handlers
5.4.1. IWrappers
5.4.2. The IHandler interface
5.5. StatusCodes
6. Advanced topics
6.1. Variants and Themes
6.1.1. Themes
6.1.2. Variants
6.2. Internationalisation
6.2.1. Internationalisation in the presentation layer
6.2.2. Internationalisation in the business logic
6.3. Authentication and authorization
6.3.1. Managing Roles
6.3.2. Custom conditions
6.3.3. Custom RoleProvider
6.4. AJAX services
6.4.1. Service configuration
6.4.2. Exception handling
6.4.3. Development tools
6.4.4. Callback mechanisms
6.4.5. Type mapping
6.5. Object-to-XML mapping
6.5.1. Serialization process
6.5.2. Built-in serializers
6.5.3. Custom serializers
6.6. Annotation-based IWrapper creation
6.6.1. IWrapper annotations
6.7. Scripted workflows
6.7.1. Parameters and Variables
6.7.2. Statements
6.8. Scripting Langauge support
6.8.1. IHandler
6.8.2. State
6.8.3. Implementation Details
6.9. Servlet Filters
6.9.1. Servlet Filter Implementation details
6.9.2. Servlet Filter Configuration
6.10. The Pustefix Editor
7. Module Support
7.1. Different module types
7.1.1. Resources within library JARs
7.1.2. Resources placed in modules/ directory
7.2. Actions applied on module resources after unpacking
7.3. Creating new modules using the Maven archetype
Glossary

List of Figures

2.1. High Level View of the system
2.2. The Pustefix backend system
2.3. Recursive XSL transformations
5.1. Pustefix servlets

List of Tables

3.1. Attributes of the <make> tag
3.2. Attributes of the <page> tag
3.3. Attributes of the <target> tag
3.4. Attributes of the <target> tag
3.5. Exception processor properties
4.1. The Core Pustefix XSLT Tags
4.2. Attributes of the pfx:button tag
4.3. Attributes of the pfx:include tag
4.4. Attributes of the pfx:maincontent tag
4.5. Attributes of the pfx:image tag
4.6. Attributes of the pfx:forminput tag
4.7. Attributes of form submit controls
4.8. Attributes of pfx:anchor
4.9. Attributes of pfx:argument
4.10. Attributes of pfx:command
4.11. Attributes of pfx:xinp[@type="text"]
4.12. Attributes of pfx:xinp[@type="radio|check"]
4.13. Attributes of pfx:xinp[@type="select"]
4.14. Attributes of pfx:option
4.15. Attributes of the pfx:checkactive and pfx:checknotactive tags
5.1. Variables of the context during processing
5.2. Attributes of an iwrp parameter

List of Examples

4.1. Using <pfx:checkfield>
6.1. Configuring roles

Introduction

Pustefix is a framework that helps you to develop web based applications (referred to as projects here).

The framework consists of two more or less independent parts:

  • A machinery to apply recursive XSLT transformations that produces the UI of the web application.

  • A Java framework that takes input from the UI to change the application data and supplies changes of the application data back to the UI.

Together, the framework acts similar to the Model-View-Controller pattern (as far as this is possible in the context of a web application).

This reference guide covers all important topics that you need to know when working with any aspects of the Pustefix framework. If you are new to Pustefix we recommend reading one of the tutorials.

Chapter 1. Installation

1.1. Requirements

Before we can get started, you have to make sure that some requirements are met by your development environment. You will need:

  • JDK 5.0 or newer

  • POSIX-like operating system (Pustefix has been tested with Linux and Mac OS X, but might also work with other systems like *BSD)

  • Apache Tomcat 5.5.x

  • Apache Ant 1.6.5 or newer

The installation of these tools (except Tomcat) is not covered by this tutorial. Please refer to the documentation provided with these tools for installation instructions.

1.2. Prepare the project directory

If you are not using Eclipse, you can just create an empty directory that will contain the project files and proceed with Section 1.3, “Unpack the skeleton”.

Start the Eclipse workbench and create a new project of type Java Project". Make sure that you choose separate source and build folders: Use src for the source and build for the build folder. This is important because the Pustefix build script expects these folders.

1.3. Unpack the skeleton

Download the newest pfixcore-skel-X.X.X.tar.gz from Pustefix's downloads page. Unpack the archive to a temporary directory. A new directory with the name skel will be created. Copy the content of this directory to your new project directory.

Now you need to download Apache Tomcat. Choose the .tar.gz archive from the download page and place it in the lib/tomcat directory of your project directory.

After you are done with that, refresh the resources view in Eclipse to make the new files appear.

1.4. Configure Eclipse

To make features like auto-completion and auto-build work, you have to import the libraries into Eclipse. Right-click on your project in Eclipse and choose "Build Path" ⇒ "Configure Build Path...". Now use the "Add JARs..." button to add all libraries from the project's lib directory.

As Pustefix generates some classes, you have to add the folder with the generated sources to Eclipse's source path. To make this work choose the "Source" tab in the same dialog you used to configure the build path and add the gensrc folder to the list of source folders.

Finally, you have to configure the path to the JAR file containing Ant. In Eclipse choose WindowPreferences. In the dialog window choose JavaBuild PathClasspath Variables. Choose New... and create a variable with the name PFX_ANT_LIB that contains the path to the lib/ant.jar within your Ant installation directory.

1.5. Build parameters & first build

Within the project directory, create a file called build.properties containing two properties:

standalone.tomcat=true
makemode=test

The first property tells the build process, that we do want to run Tomcat without Apache Httpd integration. Apache Httpd integration can be useful, because static files can be served faster. However this is an advanced topic and for our purposes Tomcat alone will be okay.

The second parameter set the so-called "make mode". This flag can be set to either "test" or "prod" and will cause the editor console to appear in web pages when in "test" mode. In fact you can even make your own settings depend on the make mode, but we will take care of this later. For the moment "test" mode is just what we want. By the way, whenever you switch the make mode, you should do a complete rebuild using ant realclean && ant to make sure, all resources have been built using the same make mode.

Now run ant to perform a first build of the environment. This will create needed symlinks and initialize the environment.

Chapter 2. Architecture

2.1. High Level View

Figure 2.1, “High Level View of the system” shows the two main parts of the Pustefix system. On the left you can see the java framework. A request coming from the browser enters the business logic. After the processing has finished, the business logic delivers the result as a (in memory) DOM tree. To get a more detailed overview of the business logic, take a look at Chapter 5, Important Concepts.

The stylesheet that's responsible to render the UI to displays the result data is requested from the XML/XSLT generator. It uses the DOM tree as input to create the HTML output that is displayed on the browser.

Figure 2.1. High Level View of the system

High Level View of the system

The stylesheet generator makes heavy use of caching to ensure that transformations are never made twice unless the result is out of date. Normally all generated stylesheets are cached in memory (and on disc). If you don't have enough memory to hold your site in RAM, you can specify other cache objects. E.g. we supply a LRU cache that can be configured to hold only the last N generated objects in memory.

2.2. The Pustefix backend system

Figure 2.2, “The Pustefix backend system” shows, how the different interfaces and classes in Pustefix are connected.

Figure 2.2. The Pustefix backend system

The Pustefix backend system

Please note that this graph is somehow out-dated as de.schlund.pfixcore.workflow.Context is no longer a class but only a interface providing the application's view on the functions provided by the "real" context implementation used by the servlet.


2.3. Recursive XSL Transformations

The XML/XSLT System of Pustefix is responsible for generating the final stylesheet that represents the static content of a page. This stylesheet is then used together with the DOM tree that holds the result of the request (as given by the business logic) to produce the final HTML output.

Figure 2.3, “Recursive XSL transformations” shows the typical transformations and files that are involved in producing the final stylesheet BazPage.xsl.

Note that we only discuss the common case here, arbitrary complex and deep transformation trees are in fact possible.

Figure 2.3. Recursive XSL transformations

Recursive XSL transformations

The red boxes are supplied by the framework, you don't need to create them yourself and as an application programmer, you can't change them. Currently this is only the case for core/xsl/master.xsl, core/xsl/metatags.xsl, core/xsl/customizemaster.xsl and other stylesheets that make up the core environment (these are not shown as they are included into master.xsl and metatags.xsl via xsl:include transparently for the user).

The green boxes are the result of XSL transformations.

The blue boxes represent files that you need to create yourself. The [PROJECT]/xsl/skin.xsl and [PROJECT]/xsl/metatags.xsl files are special, as they are not a target (see below) but just another XSLT stylesheet that can be included via xsl:include into master.xsl and metatags.xsl resp. [PROJECT]/xsl/skin.xsl contains the project specific templates that should apply on the last transformation stage, while [PROJECT]/xsl/metatags.xsl contains the project specific templates that apply only on the first stage.

There are projects that don't use a [PROJECT]/xsl/skin.xsl stylesheet at all or include even more stylesheets. Making master.xsl aware of the presence of the [PROJECT]/xsl/skin.xsl stylesheet is part of the transformation from core/xsl/master.xsl + core/xsl/customizemaster.xsl --> master.xsl

It'a also posible that a project doesn't use a [PROJECT]/xsl/metatags.xsl stylesheet or includes more stylesheets: Similar to master.xsl it's the responsibility of the transformation from core/xsl/metatags.xsl + core/xsl/customizemaster.xsl --> metatags.xsl to customize the resulting metatags.xsl to include the stylesheets.

The [PROJECT]/xml/FooBase.xml file defines the structure of the "BazPage" page (e.g. frames, the outer table structure if you do the layout with tables or divs and the like). You define one of these structural xml files for every layout you want to use in your project (the number of structural xml files is typically quite small, as many pages share the same layout).

The blue discs blue discs represent include parts. These are little snippets of XML code that make up the actual content of the page. As can be seen from the diagram, they can include each other, as long as there is no cyclic inclusion (so no include part can include itself either directly or indirectly). Include parts have a name and are organized into so called include documents. These can hold an arbitrary number of parts.

2.3.1. XSL Targets

A target is everything that is the result of a XSLT transformation as seen in Figure 2.3, “Recursive XSL transformations”. It is also obvious that a target can be used to create new targets. For the sake of completeness, the initial XML or XSL files that are used in transformations are called targets, too.

The Pustefix system knows different types of targets:

  • Leaf targets are targets that are not the result of a XSL transformation, but are read directly from files. You only edit leaf targets, never virtual targets. The distinction between XML/XSL is made depending on the purpose the target serves. An XML target is read into the system without doing any special processing, while an XSL target is compiled into a templates object that is able to transform XML input.

    Examples for leaf targets in Figure 2.3, “Recursive XSL transformations” are FooBase.xml, core/xsl/metatags.xsl and core/xsl/master.xsl.

  • Virtual targets are the result of a XSL transformation. They don't exist as files (in fact they do, but only to cache the result on the harddisk. These cache files must never be edited by hand). The difference between the XML/XSL type is the same as with the leaf targets.

    Examples for leaf targets in Figure 2.3, “Recursive XSL transformations” are BazPage.xml, and BazPage.xsl.

Chapter 3. Configuring Pustefix

3.1. Overview

Starting a new project in your Pustefix environment requires (besides developing the business logic and the UI) that you edit a bunch of configuration files.

Three different types of config files exist:

  1. The project definition file. This file is used to list all the information that is needed to generate an apache config file and the servlet container's config files for this project. Also the project info needed for the editor application is given here.

    There is a environment-wide portion of the configuration (located at DOCROOT/servletconf/projects.xml.in) that handles properties common to all projects. Additionally, there is, for each project, a file called DOCROOT/MyProject/conf/project.xml.in that contains the project specific information.

    The build system builds the final DOCROOT/servletconf/projects.xml file by merging the project specific and the environment-wide files.

  2. The second type of configuration file is a property file for (almost) all servlets that you have defined for your project in the associated project.xml file. Again, there is also a common property file used for all servlets (DOCROOT/common/conf/pustefix.xml.in) and a property files for all factory classes (DOCROOT/common/conf/factory.xml.in) that are started right at the beginning of the bootup process of the servlet container (These factories offer services that are useful for all projects running in the environment. Much of the framework itself is implemented in these factories).

    The name of the property file for each servlet can be choosen freely, but it should match the name under which the servlet is accessible. E.g. if the servlet is accessible via the URL http://some.host.com/xml/config then the name of the servlet's property file should be config.prop (But note that you must never edit the config.prop file itself, but a corresponding .prop.in file instead that follows a special XML syntax. The build process takes care to transform this file into the form needed by the framework). The file should be located in the project's conf subdirectory.

  3. The third type is a XML file that defines the UI and page structure of the project. This is also located in each project's conf subdirectory and is called depend.xml.

3.2. Configuration File Format

3.2.1. Java Property Files

Some parts of the Pustefix frameworks are configured using Java properties. To ease this configuration Pustefix provides you with a special XML format which is read instead of the usual Java property file format. This format provides some customization mechanism to allow configuration options to depend on settings like the makemode or the machine the application is being built on.

The structure of a standard .xml property file is very easy:

<standardprops version="1.0"
  xmlns="http://pustefix.sourceforge.net/2004/properties"
  xmlns:cus="http://www.schlund.de/pustefix/customize"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://pustefix.sourceforge.net/2004/properties http://pustefix.sourceforge.net/2004/properties.xsd">
  <properties>
    <prop name="statuscodefactory.messagefile">common/dyntxt/statusmessages.xml</prop>
  </properties>
</standardprops>

The cus namespace is needed to use the customization tags explained below. The prop tag is the most primitive way to enter a single property. The example above would simply result in the java property statuscodefactory.messagefile=common/dyntxt/statusmessages.xml. Pustefix allows to customize the creation of the property files in certain ways. When the file is being read, the system uses settings defined in common/conf/buildtime.prop (which itself is automatically generated by the build system) to provide the parameters used in the customization tags:

  • makemode The value of the ant property makemode, which can be passed on the ant commandline but will more commonly be specified in the environment variable MAKE_MODE. This can be used to easily switch preferences depending on the "mode" that is active when the application is built, e.g. "test" on development machines, and "prod" on the production servers. The value is supplied as the parameter mode. Note that the value of MAKE_MODE also determines if certain features are allowed like the possiblity to use the Pustefix editor or to get the XML result instead of the rendered page. These features are turned off for security reasons when the mode is "prod".

  • The user id (uid) of the user that starts the build process.

  • The full qualified domainname (as the parameter fqdn) of the machine you start the build process.

  • The name of the machine (machine) you start the build process on.

  • Any ant property (__antprop_*) defined within the build file.

Certain customization tags work with these parameters:

<properties
  xmlns:cus="http://www.schlund.de/pustefix/customize">
  <prop name="foo">
    <cus:uid/>
  </prop>
      

Use cus:uid to reference the user that started the build process. In the same way you can use cus:machine and cus:fqdn to insert the value of the supplied XSLT parameter

  <choose>
    <when test="$mode='test'">
      
    </when>
    <when test="$uid='pfixuser'">
      
    </when>
    <when test="$machine='server1'">
      

These choose and when elements are allowed only within properties elements. The three test nodes above test for one of the supplied XSLT parameters...

    </when>
    <when test="$mode='prod' and $uid='pfixuser'">
      
    </when>
    <when test="$mode='prod' or machine='server1'">
      

...you can use boolean operators to combine tests

    </when>
    <otherwise>
      

The "default test" that will always pass.

    </otherwise>
  </choose>
</properties>
      

If you think the customization system really looks like XSLT, you are almost right as in fact the test expressions are coded using XPath - the same standard XSLT is using, too.

This customization mechanism is not only available within the XML property files but also in most other Pustefix configuration files.

3.2.2. Configuration Fragments

Configuration fragments files contain aggregated configuration directives that are intended to be reused in different configuration files.

<fr:config-fragments
  xmlns:fr="http://pustefix.sourceforge.net/configfragments200609"
  xmlns:pr="http://pustefix.sourceforge.net/properties200401"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://pustefix.sourceforge.net/configfragments200609 http://pustefix.sourceforge.net/configfragments200609.xsd">
  
  <fr:navigation id="nav1">
      

All sections have an optional id that can be used to identifiy the section when more than one section fo the same type is present in one file. The value of the id attribute has to be unique within the whole file.

    <page name="MyPage" handler="/xml/myhandler"/>
      

The structure here is the same as within the navigation tag of the depend.xml file.

  </fr:navigation>
  <fr:targets>
    <standardpage name="MyPage" xml="myproject/xml/mymaster.xml"/>
      

The tags allowed here are the same that are allowed for standardpage or target definitions in the depend.xml file.

  </fr:targets>
  <fr:resources>
    <pr:resource class="com.example.MyResourceImpl">
      <pr:implements class="com.example.MyResource"/>
    </pr:resource>
      

The tags allowed here are the same that are allowed for the definition of context resources within the context tag of the ContextXMLServlet configuration.

  </fr:resources>
  <fr:interceptors>
    <pr:interceptor class="com.example.MyInterceptor"/>
      

The tags allowed here are the same that are allowed within the startinterceptors and endinterceptors tags of the ContextXMLServlet configuration.

  </fr:interceptors>
  <fr:scriptedflows>
    <pr:scriptedflow name="myscript" file="myproject/conf/scriptedflows/myscript.script.xml"/>
      

The tags allowed here are the same that are allowed within the scriptedflows tag of the ContextXMLServlet configuration.

  </fr:scriptedflows>
  <fr:roles>
    <pr:role name="MY_ROLE">
      <pr:pageaccess names="mypage*"/>
    </pr:role>
      

The tags allowed here are the same that are used for role definition in the ContextXMLServlet configuration.

  </fr:roles>
  <fr:pageflows>
    <pr:pageflow name="MyFlow">
      <pr:flowstep name="MyFirstPage"/>
      <pr:flowstep name="MySecondPage"/>
    </pr:pageflow>
      

The tags allowed here are the same that are used for the definition of pageflows in the ContextXMLServlet configuration.

  </fr:pageflows>
  <fr:pagerequests>
    <pr:pagerequest name="MyPage"/>
      

The tags allowed here are the same that are used for the definition of pagerequets in the ContextXMLServlet configuration.

  </fr:pagerequests>
  <fr:properties>
    <pr:prop name="myproperty">myvalue</pr:prop>
      

The tags allowed here are the same that are allowed within the properties tag of the ContextXMLServlet configuration.

  </fr:properties>
  <fr:directoutputpagerequests>
    <pr:directoutputpagerequest name="foo">...</pr:directoutputpagerequest>
      

Direct output pagerequests can be defined here. See Section 3.4.2, “DirectOutputServlet” for details on this.

  </fr:directoutputpagerequests>
</fr:config-fragments>
      

3.3. Project configuration

For each project in your Pustefix environment you need to create a definition file that contains all the information about your project that is needed to automatically generate other configuration files for various subsystems.

  • The apache config file, containing the definition for each of the projects of your environment: servletconf/tomcat/apache.conf

  • The config files for mod_jk: servletconf/tomcat/jk.conf and servletconf/tomcat/workers.prop.

  • The config file for the tomcat servlet container: servletconf/tomcat/conf/server.xml

  • The config files for every webapp (each project is mapped to a webapp): servletconf/tomcat/webapps/[project name]/WEB-INF/web.xml

This information is contained in a site wide file servletconf/projects.xml.in which contains information every environment needs. Each project also needs to supply a file to tell the system it's own configuration. These files are at [project name]/conf/project.xml.in. All those files, together with the site wide file are used as the source for creating the above mentioned config files.

3.3.1. The site wide configuration servletconf/projects.xml.in

The site wide projects.xml.in file contains two "projects" that are needed for Pustefix itself to work properly. The first of these is the editor project. The other project is used to start a servlet automatically when the system starts. This servlet itself is not able to act on any userinput, it's only purpose is to start a bunch of factories that implement functionality shared by other, "real" projects.

If you need other servlets for administrative purposes (e.g. to gather some sort of statisitics about the system as a whole) you can add these servlets to this project. The project specific configuration [project name]/conf/project.xml.in

<project name="test"
  xmlns:cus="http://www.schlund.de/pustefix/customize">
  <active>true</active>
  <!-- The content of this tag is used in the editor to list all defined projects. -->
  <comment>Test Application</comment>
  <depend>MyProject/conf/depend.xml</depend>

  <!-- This section is for generating apache.conf in the servletconf/tomcat directory. -->
  <virtualhost>SomeVirtualHostName</virtualhost>
  <servername>SomeServerName</servername>
  <serveralias>SomeServerAlias</serveralias>
  <defpath>/xml/SomeDefinedServlet</defpath>

  <!--
    The defpath tag names a default servlet if the user didn't specify one explicitly in
    the url (the "xml" part is the mount point of the ServletContext in which all servlets
    are running)
  -->
  <documentroot>/Path/To/DocumentRoot</documentroot>

  <!--
    The apache DocumentRoot for static content, e.g. html pages or pdf files.
    Required because otherwise apache uses its default DocumentRoot which may not be
    desirable from a security point of view. If you don't have any static content to
    server. you can use an empty directory
    Specify directories which shall not be relative to the DocumentRoot here.
    This is used for directories containing images, as they are served by apache directly.
  -->
  <passthrough>MyProject/img</passthrough>

  <literalapache>
    <-- Enter arbitrary additional stuff for the apache.conf file here. -->
  </literalapache>
  
  <ports>
    <port number="80"/>
    <!-- If you don't want to use SSL, you can remove the SSL section. -->
    <port number="443" ssl="true">
      <sslkey>/etc/httpd/conf/ssl.key/server.key</sslkey>
      <sslcrt>/etc/httpd/conf/ssl.crt/server.crt</sslcrt>
    </port>
  </ports>

  <!--
    Specify at least one servlet here. Create a config file for every servlet you
    define, as described here.
  -->
  <servlet name="myservlet" useineditor="true">
    <active>true</active>
    <class>de.schlund.pfixxml.ContextXMLServer</class>
    <propfile>MyProject/conf/myservlet.prop</propfile>
  </servlet>

  <!--
    The edit and deref servlets must always be present. The edit servlet is the
    Pustefix CMS, and the deref servlet is used to create links to external websites
    without transmitting Referer-headers which may contain the private session id.
    You don't need to create config files for these.
  -->
  <servlet name="edit">
    <active>true</active>
    <class>de.schlund.pfixxml.ContextXMLServer</class>
    <propfile>core/editor/conf/config.prop</propfile>
  </servlet>
  <servlet name="deref">
    <active>true</active>
    <class>de.schlund.pfixxml.DerefServer</class>
  </servlet>
 </project>

3.3.2. Servlet filter configuration

See Section 6.9.2, “Servlet Filter Configuration” for information on how to configure servlet filters in a pustefix application.

3.4. Servlet configuration

The processing of a request in Pustefix starts with a servlet that is derived from de.schlund.pfixxml.ServletManager. The following section explains how the different servlet types are configured.

3.4.1. ContextXMLServlet configuration format

Most projects use one or a (small) number of de.schlund.pfixxml.ContextXMLServlet servlets that drive the business logic of the application. All pages that are to be generated via XSLT from a data XML tree are handled by a servlet of this type.

This servlet uses a configuration file that has a special syntax. However properties and customization in this file work nearly the same way as explained for the standard property definitions.

  <contextxmlserver version="1.0"
    xmlns="http://pustefix.sourceforge.net/2004/properties"
    xmlns:cus="http://www.schlund.de/pustefix/customize"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pustefix.sourceforge.net/2004/properties http://pustefix.sourceforge.net/2004/properties.xsd">
    <servletinfo depend="MyProject/conf/depend.xml" name="AUniqueNameForTheServlet">
        

The attributes depend and name are mandatory. If depend starts with a '/' the value is used unchanged, otherwise (which is the usual case) it's interpreted as a path relative to the docroot.

      <editmode allow="true|false"/>
        

allow needs to be set to true if you want to be able to use the pustefix editor. You can wrap this tag within a customization element to allow edit mode only in certain modes (e.g. test mode). The whole node is optional.

      <ssl force="true|false" modes="ListOfModes"/>
        

force must be set to true if the servlet needs to run under SSL. You can wrap this tag within a customization element to force use of SSL only in certain modes (e.g. prod mode). The whole node is optional.

      <defaultstate class="a.state.Class"/>
      <defaultihandlerstate class="another.state.Class"/>
        

defaultstate and defaultihandlerstate are both optional. The class attribute must be given. a.state.Class should de a descendant of de.schlund.pfixcore.workflow.app.StaticState and another.state.Class should be a descendant of de.schlund.pfixcore.workflow.app.DefaultIWrapperState (unless you really know what you are doing). They are used to set the defaults for the state tag used when processing the pagerequest tag (see there for more info).

    </servletinfo>
    
    <context defaultflow="AFlowName" synchronized="true">
        

Attribute Description
defaultflow Mandatory. Must reference a valid pageflow (See below).
synchronized Optional. Defaults to true. If set to true, only one request per session is handled concurrently. If set to false all requests will be handled concurrently, requiring thread-safe business logic.

      <resource class="A_Resource">
        

class is mandatory, can be any Java class, that can be created with a default constructor. Usually it's a bean like class with getters and setters. There may be multiple resource tags given.

        <implements class="A_Interface">
        

The whole implements node is optional. class is mandatory, must be a Java interface implemented by the resource. There may be more than one implements tag for a resource, but each interface must be unique in the whole context. In other words: it's possible for a resource to implement more than one interface, but not possible for one interface to be implemented by two resources used in the same Context definition.

        </implements>
        <properties>
        

The whole node is optional.

          <prop name="A_Name">A_Value</prop>
        

prop is mandatory and can be used multiple times. It's similar to the use as a child of pagerequest/properties, but used here to create properties that are related to a context resource implementation. The resulting property looks like this: context.resourceparameter.A_Resource.A_Name=A_Value Customization tags may be used around a property to make it depend on a certain makemode or other parameters.

        </properties>
      </resource>
    </context>
    
    <scriptedflow name="AName" file="path/to/scriptfile.xml"/>
        

There may be an arbitrary number of scriptedflow tags, but each one must have a unique name. Scripted flows are a special method to control a session and do automatic requests based on initial user input.

    <role name="A_ROLE"/>
    <condition id="A_CONDITION"/>
    <authconstraint id="AN_AUTHCONSTRAINT"/>
        

You can define an arbitrary number of roles, conditions and authconstraints here, for details see Section 6.3, “Authentication and authorization”.

    <pageflow name="AName" final="APageName" stopnext="true|false">
         

There may be multiple pageflow tags defined, but you need at least one (which must be referenced by the defaultflow attribute above). We only describe the normal case without using variants. See here for more information on how to handle variants of pageflows.

Attribute Description
name Mandatory. Must be a unique name.
final Optional, must reference a page with a valid pagerequest definition given in this property file. There may be many pageflows defined for a servlet. A page may well be used in more than one pageflow.
stopnext Optional, defaults to false. If given and true, the pageflow will stop at the next accessible page after the current page even if this page would normally be skipped in the workflow because it doesn't need any input.

      <flowstep name="AnotherPageName" stophere="true|false">
        

Attribute Description
name Mandatory. Must reference a valid pagerequest. Usually there are many flowsteps defined in a pageflow.
stophere Optional, if true the pageflow will stop at this step unconditionally if the submit originated from a step that's before this one in the pageflow. See also the stopnext attribute of the tag which is quivalent to specifying stophere="true" for every single flowstep.

        <oncontinue applyall="true|false">
        

This tag (which is optional) starts a sequence of test/action pairs. The tests are XPath expressions which work on the DOM tree as produced by the flowstep's associated state (note that the navigation is not inserted into the DOM tree at this stage, and the /formresult/formvalues and /formresult/formerrors paths are also not present). The pageflow system calls the tests whenever a state returns a ResultDocument (before it continues with other stuff e.g. a pageflow run). The applyall attribute is optional. If given and true, all actions with matching conditions are executed, if not given or false (the default) only the first action with a matching condition is executed.

          <when test="A_XPath_Expression">
        

The when tag contains the XPath expression to try in it's test attribute. If this attribute is omitted, the whole condition is considered to be true.

            <action type="jumpto" page="APage" pageflow="APageFlow">
        

The action tag denotes the FlowStepAction to execute. The type attribute is mandatory and defines the special action to use. The string jumpto denotes the special FlowStepAction de.schlund.pfixcore.workflow.FlowStepJumpToAction which is used to set the jumptopage (defined via the page attribute) and/or the jumptopageflow (defined via the pageflow attribute).

            </action>
          </when>
          <when test="A_XPath_Expression">
            <action type="A_FlowStepAction" somekey="somevalue">
        

If the type attribute is not jumpto, the value is interpreted as a class of type de.schlund.pfixcore.workflow.FlowStepAction. There can be an arbitrary number of additional attributes (somekey in this example) which are supplied as named parameters to the special FlowStepAction.

            </action>
          </when>
        </oncontinue>
      </flowstep>
    </pageflow>
    
    <pagerequest name="APageName" copyfrom="APageName">
        

Attribute Description
name Mandatory. It must be the name of a page defined in the corresponding depend.xml file.
copyfrom Optional. If given, and set to the name of a valid pagerequest, all configuration from this referenced pagerequest are used for the current page, disregarding all configuration that is made in this pagerequest. It's a plain and simple copy, no extending, no restricting!

      <ssl force="true|false"/>
        

The node is optional. If given, and the attribute force is set to true, the page will only run under SSL when jumped to via a link or a submit of form data. If the session currently does not run under SSL, the system will make sure to redirect to a secure session prior to handling the request. After a session is running under SSL, there is no way back (so all other pages will run securely regardless if they have a ssl node or not). You can wrap this tag within a customization element to force use of SSL only in certain modes (e.g. prod mode).

[Note]Note

You can force the servlet as a whole to run only under SSL by specifying the ssl subnode of the servletinfo node.

  <state class="AClassName"/>
        

The whole node is optional. If given, the class attribute must be the name of a java class implementing the de.schlund.pfixcore.workflow.State interface. The used State is determined as follows:

  1. If state is given, use the value of it's class attribute.

  2. If the pagerequest has an input child, use the value of the class attribute of the defaultihandlerstate tag explained above if it is given. If this is not given, just use de.schlund.pfixcore.workflow.app.DefaultIWrapperState. Else:

  3. use the value of the class attribute of the defaultstate tag explained above if it is given. If this is not given, just use de.schlund.pfixcore.workflow.app.StaticState.

You can use any BSF-supported scripting language for writing your State-implementation, too.

      <finalizer class="AClassName"/>
        

The whole node is optional. It may only be given for a State that is either de.schlund.pfixcore.workflow.app.DefaultIWrapperState or a descendent of it. The class attribute is mandatory and denotes a class implementing de.schlund.pfixcore.workflow.app.ResdocFinalizer.

[Caution]Caution

The use of finalizers is not suggested most of the time! They can completely change the result document and the logic when to trigger the next step in the current page flow. Use them at your own risk. Or better: Don't use them at all.

      <input policy="ANY|ALL|NONE">
        

The whole node is optional. It may only be given for a State that is either de.schlund.pfixcore.workflow.app.DefaultIWrapperState or a descendent of it! policy is optional (default is ANY). The policy decides when a whole page is considered to be accessible:

  • ANY: just one of the associated handlers needs to be active for the page to be accessible.

  • ALL: all the associated handlers must be active for the page to be accessible.

  • NONE: none of the associated handlers needs to be active for the page to be accessible.

If one of the associated handlers returns false on calling prerequisitesMet(), the page is of course still inaccessible.

        <wrapper prefix="AName" class="AClassName" activeignore="true|false"/>
        

[Caution]Caution

Note: The tag name wrapper can also be called interface with the same allowed attributes for backwards compatibility reasons. This ambiguity may be removed in some future version.

There can be many wrapper nodes for a page. Each one references an "atomic" functional entity consisting of an IWrapper java class (usually autogenerated from a .iwrp xml file that defines the type and names of the parameters passed between the UI and the functional entity and an associated IHandler java class that uses the IWrapper to retrieve the passed parameters via typed getter methods.

Attribute Description
prefix Mandatory. The prefix defines a name for the IWrapper and in effect a namespace for the IWrapper's parameters. If the prefix "bar" is defined for an IWrapper that contains a parameter called "Foo", the submitted HTTP parameter must be called bar.Foo.
class Mandatory. Must be the name of a java class implementing de.schlund.pfixcore.generator.IWrapper. This implicitly defines a de.schlund.pfixcore.generator.IHandler, as every IWrapper knows it's associated IHandler and can be queried for it.
activeignore Optional, default is false. The IHandler method isActive() is NOT called on handlers with activeignore set to true. In other words: the handler is ignored when the system tries to find out if the page is accessible or not. See also the comment for the policy attribute above.

      </input>
        

      <process>
        

The process node holds a list of actions, which can be referenced from the UI when submitting forms or using GET requests to transmitt data. These actions group IWrappers into two groups: those that should have their handleSubmittedData() method called, and those that should have their retrieveCurrentStatus() method called when a submit has been handled sucessfully (and the same page is redisplayed). The idea beind the latter is, that sometimes you want to update the submitted form data to some canonical form (e.g. adresses or similar), so you don't want to see the exact same input in the form elements as you have submitted it, but some changed values. In other cases, submitting data to one wrapper may change the values of the form elements of another wrapper - in this case the second wrapper needs to be listed under the <retrieve> node.

        <action name="a_name">
          <submit>
            <wrapper ref="a_prefix_1"/>
            <wrapper ref="a_prefix_2"/>
            ...
          </submit>
          <retrieve>
            <wrapper ref="a_prefix_1"/>
            <wrapper ref="a_prefix_X"/>
            ...
          </retrieve>
        </action>
        <action name="another_name">
        ...
        </action>
      </process>
      
      <output>
        

The whole node is optional. Every page using a State that is itself or a descendant of de.schlund.pfixcore.workflow.app.StaticState can use this. You can have as many resource childnodes as you like.

        <resource node="AName" class="AClassName"/>
        

Attribute Description
class Mandatory. class is one of the ContextResources defined via implements above.
node Mandatory. node is the node in the output tree ("/formresult/AName") under which the ContextResource inserts it's data.

      </output>
      
      <properties>
        

The whole node is optional.

        <prop name="APropertyKey">AValue</prop>
        

The node is mandatory and can be used multiple times. It will be transformed into a java property that is associated to the page. There are some props that are already defined for de.schlund.pfixcore.workflow.app.StaticState and descendants. These are listed below

Property Name Property Value Description
mimetype e.g. text/css If given, sets the mimetype of the HttpResponse object to something else than the default text/html. This is most often used for text/css.
responseheader.A_HEADER A_VALUE If given, set the header A_HEADER of the HttpResponse object to A_VALUE. NOTE: the Pustefix system uses a set of default headers that are only used, when no user defined headers are given! The set of default headers is: Expires=Mon, 26 Jul 1997 05:00:00 GMT Cache-Control=private If you want to use some of them in addition to your own headers, you must manually supply them, too.

      </properties>
    </pagerequest>
    
    <config-include file="myproject/conf/myfile.xml" section="pagerequests"/>
        

Includes a part of a config fragments file at this location. See Section 3.2.2, “Configuration Fragments” for details on how to define config fragments.

Attribute Description
file Mandatory. Path to the file that contains the tags to be included (relative to docroot).
section Optional. Type of the section that shall be included. If more than one section of the specified type exists in the file, the content of all this sections is included.
refid Optional. Include a section identified by the specified id. The refid specified here must match the id attribute of exactly one section in the specified file.
xpath Optional. A XPath expression specifying the node-set to be included. The prefixes to be used for XML namespaces are "fr" for the namespace of the fragments file tags and "pr" for the namespace of the ContextXMLServlet configuration tags.

One and only one of the section, refid or xpath attribute has to be specified for each config-include.

    <properties>
      <prop name="AProperty">AValue</prop>
        

Property Name Property Value Description
mimetype e.g. text/css If given, sets the mimetype of the HttpResponse object to something else than the default text/html. This is most often used for text/css.
responseheader.A_HEADER A_VALUE If given, set the header A_HEADER of the HttpResponse object to A_VALUE. Headers set here can be overwritten for specific pages. NOTE: the Pustefix system uses a set of default headers that are only used, when no user defined headers are given! The set of default headers is: Expires=Mon, 26 Jul 1997 05:00:00 GMT Cache-Control=private If you want to use some of them in addition to your own headers, you must manually supply them, too.

You can also specify properties here that are understood by the ServletManager class.

    </properties>
  </contextxmlserver>
        

3.4.2. DirectOutputServlet

Occasionally you don't want to generate output with an XSLT Transformation, but e.g. deliver binary content directly to the output stream instead. In this case you need to provide another servlet of type de.schlund.pfixxml.DirectOutputServlet. This servlet doesn't have it's own Context object but instead "hijacks" the Context of a foreign de.schlund.pfixxml.ContextXMLServlet. The context isn't used for any pageflow handling, only as a means to get to the data (via its ContextResources) of the "main" application.

The servlet knows about one or many directoutputpagerequests. For the XML/XSLT side of things, they look like normal pages (in fact, the value of the directoutputpagerequest's name attribute must be a page defined in depened.xml. Of course, no target definition has to be given, only the page in the navigation structure must exist). But other than the usual pagerequest, a directoutputpagerequest has an associated directoutputstate whose class attribute is a java class implementing de.schlund.pfixcore.workflow.app.DirectOutputState.

  <directoutputserver version="1.0"
    xmlns="http://pustefix.sourceforge.net/2004/properties"
    xmlns:cus="http://www.schlund.de/pustefix/customize"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pustefix.sourceforge.net/2004/properties http://pustefix.sourceforge.net/2004/properties.xsd">
    
    <directoutputservletinfo depend="MyProject/conf/depend.xml" name="AUniqueNameForTheServlet">
      <ssl force="true|false"/>
      <editmode allow="true|false"/>
        

See the comment for the servletinfo node in Section 3.4.1, “ContextXMLServlet configuration format”.

    </directoutputservletinfo>
    
    <foreigncontext externalservletname="UniqueNameOfAnotherServlet" synchronized="true"/>
         

The externalservletname must reference the name of a servlet of type de.schlund.pfixxml.ContextXMLServlet. The Context (or better: the ContextResourceManager) of this servlet is used for getting stored application data. The synchronized attribute is optional. It defaults to true. If set to true, only one request per session is handled concurrently. If set to false all requests will be handled concurrently, requiring thread-safe business logic.

    <authconstraint ref="AN_AUTHCONSTRAINT"/>
         

You can reference an authconstraint from the context configuration, which has to be fulfilled to access a page. This default authconstraint can be overridden for single pages. If no default authconstraint is set here, the context's default authconstraint will be used. If no authconstraint is set at all, a page requires no authentication.

    <config-include file="myproject/conf/myfile.xml" section="directoutputpagerequests"/>
         

Includes a part of a config-fragments at this location. See Section 3.2.2, “Configuration Fragments” for details on how to define config fragments.

Attribute Description
file Mandatory. Path to the file that contains the tags to be included (relative to docroot).
section Optional. Type of the section that shall be included. If more than one section of the specified type exists in the file, the content of all this sections is included. For a DirectOutputServlet configuration only directoutputpagerequests and properties are valid.
refid Optional. Include a section identified by the specified id. The refid specified here must match the id attribute of exactly one section in the specified file.
xpath Optional. A XPath expression specifying the node-set to be included. The prefixes to be used for XML namespaces are "fr" for the namespace of the fragments file tags and "pr" for the namespace of the DirectOutputServlet configuration tags.

One and only one of the section, refid or xpath attribute has to be specified for each config-include.

    <directoutputpagerequest name="APageName">
      <directoutputstate class="AClassName"/>
        

      <authconstraint ref="AN_AUTHCONSTRAINT"/>
        

You can optionally reference an authconstraint from the context configuration to override the default authconstraint.

      <properties>
        

The whole properties node is optional.

        <prop name="APropertyKey">AValue</prop>
        

The node is mandatory and can be used multiple times. It will be transformed into a java property that is associated to the page. The java property that is constructed will look like this: pagerequest.APpageName.APropertyKey=AValue where APageName is the value of the name attribute.

      </properties>
    </directoutputpagerequest>
  </directoutputserver>
        

3.5. Page Configuration (depend.xml)

The depend.xml configuration file serves two purposes: First, it is used to create the hierarchical page structure of the project by defining a tree of pages. Then, it is used to define the internal structure of the pages by defining, for every single page, the tree of transformations that need to be applied to certain files to get the final stylesheet (which is the representation of the page in Pustefix). For an overview over the transformation aspect of the whole framework, please go here.

To make life a little easier, you can use convenience tags that are automatically transformed by the runtime system when the file is loaded.

3.5.1. Structure of the depend.xml

The structure of the config file is show below:

<make project="MyProject" lang="en" themes="ThemeA ThemeB ... default">
  <navigation>
    <page name="foo" handler="/xml/static" accesskey="F">
      <page name="sub_foo1" handler="/xml/static"/>
      <page name="sub_foo2" handler="/xml/static"/>
    </page>
    <page name="bar" handler="/xml/config">...</page>
    
    <!-- Configuration fragements are supported as well -->
    <config-include file="myproject/conf/myfile.xml" section="navigation"/>
  </navigation>

  <!--
    The global section allows to set default values for ALL pages defined via the
    standardpage tag (see below). It's possible to set default params, and runtime
    stylesheets (see here). It's also possible to add more runtime stylesheets or
    overwrite params in the standardpage tag for a single page.
  -->
  <global>
    <param name="AName" value="AValue"/>
    <include stylesheet="path/to/AStyleSheet"/>
  </global>

  <config-include file="myproject/conf/myfile.xml" section="targets"/>

  <!--
    The only other tags allowed besides the navigation tag are target, global,
    standardmaster, standardmetatags and standardpage. The latter three are only
    convenience tags that can be expressed fully in terms of target tags
    (Expanding those tags is one of the duties of the runtime transformation of
    the depend.xml file mentioned above).
  -->
  <target name="a_target_name.xsl" type="[xsl|xml]">...</target>
  <target name="another_target_name.xml" type="[xsl|xml]">...</target>...
  <standardmaster name="..."/>
  <standardmetatags name="..."/>
  <standardpage name="a_name" master="..."
                metatags="..." themes="..." variant="..."
                xml="a_base_xml_file.xml">
    ...
  </standardpage>
</make>

3.5.2. The <make/> tag

The <make> tag is the root element of the depend.xml

Table 3.1. Attributes of the <make> tag
Attribute Mandatory? Description
project mandatory The name of the project. This is the same as the corresponding entry in the project.xml.in file.
lang mandatory The default language of the project. This is the same as the value of the lang node's name attribute used in include parts.
themes optional

The attribute is a space separated list of theme names. It acts as a fallback queue of product branch names that should be checked in include parts to decide which branch to use. The least specific theme is always the "default" theme and therefore "default" should be the last theme in the list. The last theme in the list is used when a non-existing include part is created in the Pustefix CMS, so you can omit the "default" theme from the end of the list if you want to use another theme for newly created include parts. However the "default" theme will still be used as a fallback for existing include parts when no other matching theme variant of the include part exists. You should have at least a product branch named "default" in every include part to make sure to always have a valid fallback.

If it's not given, it defaults (in our example where the project name is "MyProject") to "MyProject default".

Note that this attribute only defines a global value, each target can define it's own themes list (see below for targets and their attributes).

The allowed characters for themes are: a-zA-Z0-9_+-

3.5.3. The <page/> tag

The <page> tag defines all available pages.

Table 3.2. Attributes of the <page> tag
Attribute Mandatory? Description
name mandatory The name of the page. This name is used throughout Pustefix to reference the page (e.g. when creating internal links and in other config files). The allowed characters for page names are: a-zA-Z0-9_+-
handler mandatory This attribute tells the system which servlet is used to handle requests for this page. You can think of the handler attribute as a project wide servlet "name" as defined in the project definition
accesskey optional This attribute defines a default access key that will be used by the pfx:button tag for the links it generates.

3.5.4. Target definition

The <target> tag is used to specify the XSL transformations in Pustefix. In most cases, you will not have to use the rather complex <target>, but use the convinience tags described in Section 3.5.5, “Standard page definition”, Section 3.5.6, “Standard master target definition” and Section 3.5.7, “Standard metatags target definition”.

Section 2.3.1, “XSL Targets” provides more information on the concept of targets in Pustefix.

<target name="baz.xsl" type="xsl" page="foo" variant="bar" themes="Theme_A Theme_B ... default">
  <!--
    depxml and depxsl reference other targets by their name attribute
    that serve as the XML resp. XSL input used to create this target
    via a XSL transformation. If for a given name attribute of either
    depxml or depxsl no other target definition is found, the transformation
    parent is supposed to be a leaf target and the name attribute is 
    interpreted as a path relative to the docroot.
  -->
  <depxml name="foo/xsl/bar.xsl"/>
  <depxsl name="foo/xsl/baz.xsl"/>

  <!--
    Additional dependencies
  -->
  <depaux name=