2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

Shale Dialog Manager (SCXML Implementation)

Introduction

The Shale Dialog Manager defines a generic API by which an application may utilize a Dialog Manager implementation to manage conversations with the user of that application. A user may have (at most) one active conversation in each window or frame that he or she is using.

This module contains the SCXML (State Chart XML) Implementation of the Shale Dialog Manager facilities. It uses the Commons SCXML library for the dialog state machine execution under the covers, and the dialogs are described using SCXML documents.

Benefits

  • SCXML is a W3C Working Draft which may translate to better support in tooling, number of implementations and various runtime environments. It is the candidate controller notation coming out of the W3C.
  • SCXML is more closely aligned to state chart theory and UML2, which helps those using model driven development methodologies.
  • SCXML semantics provides for much more than the basic Shale dialogs implementation, such as histories, per state contexts, arbitrary expression evaluation, parallelism and the possibility (currently not available in the shale-dialog-scxml module) to add domain-specific XML vocabularies via action namespaces. See the Commons SCXML site for details.
  • Those developing multi-channel applications, or using frameworks that use SCXML for the controller bits in other contexts (e.g. RDC framework), may be inclined towards SCXML-based authoring for Shale dialogs.

Describing Shale dialogs via SCXML documents

A Shale dialog is modeled as a state machine. The various "state types" that commonly constitute the dialog state machine are described in the Shale dialogs basic implementation documentation.

This section maps these types to the corresponding SCXML snippets appropriate for the Shale dialogs SCXML implementation. The example dialog from the Shale usecases sample application is captured here as a UML state machine diagram and forms the basis of the snippets below.

  • Action state instances may be mapped to executable content in UML <onentry> (and may be chained similarly).
    <!-- An "action" state -->
    <state id="checkCookie">
    
      <!-- Execute the method binding expression in the onentry block,
          method must take no arguments and return a String. These
          method binding expressions must use the #{...} syntax -->
    
      <onentry>
        <var name="cookieOutcome" expr="#{profile$logon.check}" />
      </onentry>
    
      <!-- Check the return value, and conditionally transition
          to the appropriate state. Arbitrary EL expressions must use
          the ${...} syntax. Since transitions are not guarded by
          events, the transitions are "immediate" -->
    
      <transition cond="${cookieOutcome eq 'authenticated'}"
          target="exit"/>
      <transition cond="${cookieOutcome eq 'unauthenticated'}"
          target="logon"/>
    
    </state>
    
  • View state instances use event guards to wait for postback. The mapping between the <state> id and the JavaServer Faces view identifier is pluggable. The default mapping is an identity transform i.e. the state identifier is reused as the view identifier. See the DialogStateMapper Javadocs for details. This mapping may be overridden by using the <shale:view> custom Commons SCXML action. See the Shale dialogs custom Commons SCXML actions section for details. Also note the associated best practices when authoring view <state>s.
    <!-- A "view" state, the default convention maps this state to
        to the JSF view identifier "/logon" -->
    <state id="logon">
    
      <!-- Wait for postback event, which is named "faces.outcome"
          The reserved variable "outcome" contains the logical
          outcome, which is used to conditionally transition
          to the next state -->
    
      <transition event="faces.outcome"
          cond="${outcome eq 'authenticated'}"
          target="exit"/>
      <transition event="faces.outcome"
          cond="${outcome eq 'create'}"
          target="createProfile"/>
    
    </state>
    
  • Subdialog state instances may be mapped to external SCXML documents (describing the subdialog) via the "src" attribute of the SCXML <state> element.
  • <!-- A "subdialog" state, the "src" attribute points to the SCXML
        document describing the subdialog. -->
    <state id="createProfile" src="edit-profile.xml">
    
      <!-- Wait for <state_id>.done event, which lets us know
          the subdialog has run to completion. This subdialog uses the
          the "outcome" variable to convey its logical outcome to the
          parent dialog (the SCXML <assign> element can be used
          to assign values to existing variables) -->
    
      <transition event="createProfile.done"
          cond="${outcome eq 'success' or outcome eq 'cancel'}"
          target="exit"/>
      <transition event="createProfile.done"
          cond="${outcome eq 'failure'}"
          target="fail"/>
    
    </state>
    
  • End state instances may be mapped to SCXML final states.
    <!-- An "end" state, signifies that the dialog has run to
        completion, the default convention maps this state to
        to the JSF view identifier "/exit". -->
    <state id="exit" final="true"/>
    
    Once the dialog reaches an end state, the dialog manager cleans up the current instance of the executing dialog.

Using Dialog Manager (SCXML implementation)

To use the SCXML Dialog Manager facilities in Shale, take the following steps:
  • Model your dialog as a series of States with transitions between them labelled with the logical outcome that selects that particular transition. A UML State Diagram is a very useful mechanism for visualizing such a model. Then create a SCXML document for each of the dialogs (dialog state machine diagrams can be easily mapped to SCXML documents, see above section).
  • Build the views (and corresponding ViewController beans, if you are also using the Shale View Controller Support functionality) that comprise your dialog, using standard JavaServer Faces and (optional) Shale ViewController facilities.
  • Declare your dialogs via an XML document, conventionally named /WEB-INF/dialog-config.xml, that conforms to the required DTD:
    <!DOCTYPE dialogs PUBLIC
      "-//Apache Software Foundation//DTD Shale SCXML Dialog Configuration 1.0//EN"
      "http://shale.apache.org/dtds/dialog-scxml-config_1_0.dtd">
    
    <dialogs>
    
      <dialog name="FirstDialogName"
           scxmlconfig="firstdialog.xml"
           dataclassname="org.apache.shale.examples.FirstDialogData"
           />
    
      <dialog name="SecondDialogName"
           scxmlconfig="seconddialog.xml"
           dataclassname="org.apache.shale.examples.SecondDialogData"
           />
    
      ...
    
    </dialogs>
    
  • If you have more than one dialog configuration file, or you have defined your only dialog configuration file as a web application resource with a name different than the one described above, use a context initiaization parameter to define a comma-delimited list of context-relative paths to configuration resources to be loaded:
    <context-param>
      <param-name>org.apache.shale.dialog.scxml.CONFIGURATION</param-name>
      <param-value>/WEB-INF/foo.xml,/WEB-INF/bar.xml</param-value>
    </context-param>
    
  • In addition to the dialog configuration resources defined by this context initialization parameter, a resource named /WEB-INF/dialog-config.xml will be automatically processed, if it exists, and has not already been loaded.
  • Alternatively, or in addition to the above, any JAR file in /WEB-INF/lib will be scanned for configuration documents at META-INF/dialog-config.xml. Such resources will be automatically processed, making it easy to define JAR files with dialog configurations and corresponding Java classes and resources, which are recognized simply by including this JAR file in the application.
  • To initiate a dialog named "xxxxx", use one of the techniques defined by the Shale Dialog Manager.

Custom Commons SCXML actions

The Shale dialogs Commons SCXML implementation provides a couple of custom Commons SCXML actions out of the box ( background reading on custom actions). The first one allows the use of redirects while navigating to a view, and the second allows overriding the DialogStateMapper mapping between a "view" state and the associated JSF view identifier.
  • <shale:redirect> - Typically used in the <onentry> section of the "view" <state> that should be visited by issuing a redirect.
    <onentry>
      <shale:redirect/>
    </onentry>
    
  • <shale:view> - Typically used in the <onentry> section of the "view" <state>, such that the "viewId" attribute contains the JSF view identifier that should be rendered when in this dialog state.
    <onentry>
      <shale:view viewId="/faces/wizardpage3" />
    </onentry>
    
The shale prefix used above is arbitrary. The association is made using the namespace URI associated with the prefix (the above custom actions belong to the http://shale.apache.org/dialog-scxml URI), so the SCXML document describing the above dialog would need to establish that prefix to namespace URI association, for example:
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0"
       xmlns:shale="http://shale.apache.org/dialog-scxml"
       initialstate="...">

It is possible for application developers to define additional custom actions per dialog definition. For example, a developer may define a custom Commons SCXML action via a class my.actions.Foo (which must extend org.apache.commons.scxml.model.Action, see background reading link above) and make it available in the namespace URI http://foo.bar/actions to the dialog named "wizard" by defining it in the dialog-config.xml like so:

<dialog name="wizard" scxmlconfig="wizard.xml"
           dataclassname="wizard.Data">

    <scxmlaction name="foo" uri="http://foo.bar/actions"
                    actionclassname="my.actions.Foo" />

</dialog>
and further using it in the wizard.xml SCXML document like so:
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0"
       xmlns:shale="http://shale.apache.org/dialog-scxml"
       xmlns:my="http://foo.bar/actions"
       initialstate="...">

    ...

    <state id="state1">
        <onentry>
            <my:foo .../>
        </onentry>

        ...

    </state>

Best practices

The particular usecase of SCXML within Shale dialogs implies certain restrictions on the SCXML document used to describe the dialog. In particular, best practices for SCXML documents used to describe Shale dialogs include:

  • A "view" <state> must be a simple leaf state (should not contain other <state> elements and should not have a <parallel> ancestor).
  • A "view" <state> must not rely on <onexit> or <onentry> executable content. Such executable content can be moved to a preceeding or following "action" state. This is due to the possibility of browser navigation buttons (back/forward) being used during the dialog execution. The exception to this is the two custom actions described in the previous section, when used as mentioned above.
  • All views that participate in a dialog should provide for checks to guard against double submits (see <token> tag in shale-core) and provide "immediate" actions such as a cancel button to exit out of the dialog.