How it works

There are two web events that the WFNM framework has to handle in order to work properly:

The WFNM framework also allows to handle server side navigation history by keeping track of visited webflows and visited web pages, using a "stack of stacks" data structure stored in the user http session: the external stack is a stack of visited webflow, whether the internal stack is a stack of visited web pages for that webflow.

This section explain also the concept of ownership: every object kept into the http session (excluding the "stack of stack" data structure itself) is tied to a webflow (an element of the external stack) or to a page (an element of the internal stack): an object tied to such that element is said owned by that element.

Various policies can be configured in order to tie each object to the correct element of the stack (external or internal).

The implementation of other features is explained as well.

Handling binding/unbinding objects from http session

For handling binding/unbinding of objects from http session, the filter SessionBindingFilter is used.

This filter replaces the servlet request with a HttpServletRequestWrapper, which define the methods getSession() and getSession(boolean) in order to return the http session wrapped by the class HttpSessionWrapper.

The class HttpSessionWrapper is able to notify to the WFNM framework that an object is added/removed to/from the http session.

The following configuration is needed in order to enable the SessionBindingFilter:

<!-- WFNM Session Binding Filter -->
<filter>
   	<filter-name>wfnmSessionBindingFilter</filter-name>
   	<filter-class>net.sf.wfnm.web.SessionBindingFilter</filter-class>
</filter>

<!-- WFNM Session Binding mapping -->
<filter-mapping>
  	<filter-name>wfnmSessionBindingFilter</filter-name>
   	<url-pattern>/*</url-pattern>
</filter-mapping>

Handling pages notification

When a web page is reached, the WFNM framework has to update its internal data structure and, if necessary, remove from the http session objects which are no more useful.

The best way to implement this kind of notification is to use the PageNotifierFilter, which internally uses the NotifyFactory in order to notify that a page has been reached.

Note that the notification that a web page has been reached must work for both FORWARD and REQUEST: only the servlet 2.4 specification (i.e: J2EE 1.4) allows to configure a filter in such that way, for example with the following configuration:

<!-- WebFlow Navigation Manager filter -->
<!-- WFNM Page Notifier Filter -->
<filter>
   	<filter-name>wfnmPageNotifierFilter</filter-name>
   	<filter-class>net.sf.wfnm.web.PageNotifierFilter</filter-class>
</filter>

<!-- WFNM Page Notifier Filter mapping -->
<filter-mapping>
	<filter-name>wfnmPageNotifierFilter</filter-name>
	<url-pattern>/jsp/*</url-pattern>
	<dispatcher>FORWARD</dispatcher>
	<dispatcher>REQUEST</dispatcher>
</filter-mapping>

If a Servlet2.4/J2EE 1.4 environment is not available, it is possible to use a workaround: to add at the very end of each JSP page (or to a common template, if Tiles is used) a tag <wfnm:notify/>

In fact, the tag NotifyTag internally uses the same NotifyFactory used by the PageNotifierFilter filter.

Handling server side navigation history

The WFNM framework keeps a server side navigation history of visited webflows and pages. The internal data structure used by WFNM is a "stack of stacks", that can be showed as follow:

In the above image, the external stack of webflows contains webflow A, B and D. Each webflow contains a stack of visited pages.

The concept of ownership

The WFNM framework keeps track of every object that is placed into the http session by associating it to an element of the stack (internal or external), i.e. to a webflow or a page.

An object tied to such that element is said owned by that element.

When the element is removed from the stack, every object owned by the element itself is removed from the http session.

There are three levels at which automatic session cleaning policy can be configured:

  • Global default: it is basically a default for every webflow (see configuration) .
  • Single webflow: every webflow can be configured to have a specific policy (see the webflow tag) .
  • Single object: it is possible to change the policy even for an object that will be inserted into the http session with a specific key (see the owner tag) .
For each of the above level, the policy can be configured as follows:
  • "page": the objects are removed when a page is closed (i.e.: when returning to a previous page)
  • "webflow" (the default): the objects are removed when a webflow is closed (i.e.: when returning to a previous webflow)
  • "previous": the objects are removed when the previous webflow (i.e.: the webflow who's called the current webflow) is closed.
  • "working": the objects are removed when the second opened webflow is closed (often the first webflow contains "global" pages like login and home pages, so the second can be considered as a "working" webflow)
  • "global": the objects are removed when the very first opened webflow is closed (used to keep object in session while the WFNM is active)
  • "none": the objects are never removed from http session by WFNM
Furthermore, the WFNM cleaning subsystem can be centrally disabled if it is not considered useful.

Other features

There are other three features that the WFNM framework provides:

  • avoid multiple form submits
  • transparently add a 'no-cache' directive to requests
  • log session size statistics

The first feature is implemented with a filter called NoMultipleSubmitFilter, which executes only the first submit and simply reload the reached page for other submits.

An example configuration of such that filter is the following:

<!-- WFNM No Multiple Submit Filter -->
<filter>
   	<filter-name>wfnmNoMultipleSubmitFilter</filter-name>
   	<filter-class>net.sf.wfnm.web.NoMultipleSubmitFilter</filter-class>
</filter>

<!-- WFNM No Multiple Submit Filter mapping for Struts -->
<filter-mapping>
   	<filter-name>wfnmNoMultipleSubmitFilter</filter-name>
   	<servlet-name>Struts Servlet</servlet-name>
   	<dispatcher>REQUEST</dispatcher>
</filter-mapping>

<!-- No Multiple Submit Filter mapping for JavaServer Faces -->
<filter-mapping>
   	<filter-name>wfnmNoMultipleSubmitFilter</filter-name>
   	<servlet-name>Faces Servlet</servlet-name>
   	<dispatcher>REQUEST</dispatcher>
</filter-mapping>

The second feature is implemented with the PageNotifierFilter, which is able to transparently add the 'no cache' header directive to all requests.

Please refer to this section for a sample configuration of the PageNotifierFilter .

The session size statistic is implemented with a factory called StatsFactory.