Shale Dialog2 Framework

Introduction

The Shale Dialog2 Framework is designed to allow configuration of a "dialog" or "conversation" with a user, which may span multiple HTTP requests. While such a dialog is in progress, the framework will also maintain a "data" object representing the state of the current computation, and throw that data object away when the conversation is completed, without waiting for the user to log off so that the user's session will be cleaned out.

Design goals for the framework include the following:

The remaining sections below provide more details about the generic framework APIs and functionality exposed to application developers. However, many details of the actual functionality (including configuration resource formats) will be specific to the particular implementation of the Dialog2 Framework that you select for your application, so be sure to consult the JavaDocs for that particular package as well.

Fundamental Concepts

The Shale Dialog2 framework operates on the following primary abstractions:

While a DialogContext instance is active for a particular JavaServer Faces view, it takes over the usual implementation of the JavaServer Faces NavigationHandler. After the Invoke Application phase completes, a custom navigation handler will call the advance() on the active DialogContext instance. This method is presumed to advance the state of the underlying dialog until a JavaServer Faces view needs to be displayed to the user. At that point, the advanced() method returns the required view identifier (or null to redisplay the current view, consistent with standard JavaServer Faces navigation), and the requested view is rendered to the user.

If there is no active DialogContext for the current view, the custom NavigationHandler delegates to the standard JavaServer Faces NavigationHandler. Because of this, you may freely intermix views managed by the dialog framework and views managed by standard JavaServer Faces navigation rules, in the same application.

It is quite often useful to maintain a set of information about the state of the current dialog's computation, across multiple requests to the server. When a particular dialog instance is completed, the corresponding information can be thrown away. The Dialog2 Framework supports these requirements by supporting a general purpose data property (of type Object) on the DialogContext instance. The data type of this object can be anything useful for the dialog being executed, but will typically be either a JavaBean containing properties for each individual information item comprising the state of the computation for this dialog, or a Map where key/value pairs can easily be stored. When the dialog instance has completed its computation, the data object will have all references to it removed, so that it can be garbage collected.

Of particular note is the fact that JavaServer Faces value binding expressions can be used to bind visual components to values in the data object. For example, assume that the dialog is managing a wizard dialog for updating a user profile, and one of the properties that can be edited is the user's full name. One can bind an input text component directly to the corresponding property like this, with no need for intermediate copying as the various pages of the wizard dialog are navigated:

    <h:inputText id="fullName" value="#{dialog2.data.fullName}"/>

Creating A New DialogContext Instance

If the current view does not have an active DialogContext instance associated with it, there are several approaches available to creating a new instance and associating it with the current view:

In the latter case, there is an additional option to cause the newly created dialog instance to be associated with a parent dialog instance for the same user. This is accomplished by specifying an additional request parameter specified by Constants.PARENT_ID (literal value is org.apache.shale.dialog2.PARENT_ID), whose value is the dialog id of an active dialog for this user.

The most common use case for this special parent/child relationship is where the main page that a user is executing is under control of a named dialog, and the application wishes to display a popup window (under the control of its own dialog, and therefore its own DialogContext intsance) that can access the data of the parent dialog instance, via a value binding expression like #{dialog2.parent.data.fullName} from within the popup dialog's execution. In this way, you can easily create popup dialogs that can pull initial state information from the main window, perform arbitrary operations on it, and push results back to the main window ... with the only coupling being agreement on the names of properties in the parent dialog's data object to be used for communication.

Removing An Existing DialogContext Instance

The precise mechanism by which a DialogContext is removed is dependent upon the implementation selected, but typically an implementation will allow the application developer to specify an "end state" that, when advance() reaches that state, will cause the remove() method on the DialogContextManager instance for the current user to be called. This will trigger any necessary cleanup, including releasing all references to the data object for the removed DialogContext instance so that it can be garbage collected.

Packaging a Dialog2 Implementation

Any implementation of the Shale Dialog2 APIs should conform to the following requirements:

If these requirements are met, an application developer may select a particular implementation simply by dropping its corresponding JAR file (and any external dependencies that the implementation also requires) into the /WEB-INF/lib directory of a web application, and the implementation will be self configured.

Available Implementations

The Shale Sandbox currently contains two implementations of the Dialog2 Framework: