Table of Contents
List of Figures
List of Tables
List of Examples
<pfx:checkfield>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.
Table of Contents
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.
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.
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.
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 ⇒ .
In the dialog window choose ⇒ ⇒
. Choose
and create a variable with the name PFX_ANT_LIB
that contains the path to the lib/ant.jar within your
Ant installation directory.
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.
Table of Contents
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.
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.
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

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.
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.
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.
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.
Table of Contents
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:
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.
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.
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.
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.
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>
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.
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>
See Section 6.9.2, “Servlet Filter Configuration” for information on how to configure servlet filters in a pustefix application.
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.
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 |
|---|---|
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:
If state is given, use the value of it's
class attribute.
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:
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 |
|---|---|
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 |
|---|---|
Note: The tag name |
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>
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>
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.
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>
The <make> tag is the root element of the
depend.xml
| 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_+- |
The <page> tag defines all available
pages.
| 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. |
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=