Package org.szegedi.spring.web.jsflow

JavaScript Web Flow for Spring


Interface Summary
FlowExecutionInterceptor An interface for objects that can intercept execution of a flow, and perform operation before and after it.
FlowStateStorage A storage for interim flow states.
HttpSessionFlowStateStorage.ContinuationCallback Should be implemented by classes used as callbacks for HttpSessionFlowStateStorage.forEachContinuation(HttpSession, ContinuationCallback)
LibraryCustomizer A class implementing this interface can hook into the initialization of the global library scope and manipulate it in any way it desires.
ScriptSelectionStrategy Interface for objects that select the flowscript to execute for a flow initiating HTTP requests.
SecurityDomainFactory Classes implementing this interface can be plugged into the ScriptStorage to provide creation of Rhino security domain objects for scripts.
StateExecutionInterceptor Interface that can be used as an "around" interceptor for each state execution.

Class Summary
ClientSideFlowStateStorage An implementation of the flowstate storage that returns the BASE64-encoded serialized state as the ID.
FlowController A Spring MVC Controller that uses Rhino ECMAScript engine to implement flows.
HostObject An internal host object used to implement built-in functions for scripts.
HttpSessionFlowStateStorage An implementation for flow state storage that stores flow states in the HttpSession objects.
JdbcFlowStateStorage A flow state storage that operates against a JDBC data source.
OpenContextInViewInterceptor A Spring handler interceptor that opens a Rhino context and associates it with the current thread for the complete duration of the handling, including view rendering.
ScriptStorage A loader and in-memory storage for compiled flowscripts.
UrlScriptSelectionStrategy A script selection strategy that uses the components of the request URL to select a script to run.

Exception Summary
FlowStateStorageException Thrown when AbstractFlowStateStorage persistence fails.

Package org.szegedi.spring.web.jsflow Description

JavaScript Web Flow for Spring

What is it?

JavaScript Web Flow for Spring is a controller component for the MVC architecture of the Spring Framework that uses scripts written in the ECMAScript language (more widely known as "JavaScript") to drive web flows. A web flow is a multi-step series of HTTP requests and responses that comprise a single logical operation (i.e. a checkout procedure in a webshop taking several webpages). JSFlow is built on top of the Mozilla Rhino ECMAScript interpreter, and leverages its support for continuations.

Why does it exist?

For pretty much the same purpose Spring Web Flow exists. Instead of repeating the arguments presented there, we'll just direct you to read this article about it and then return to us.

Ok, then why a different implementation?

While we agree with the goals Spring Web Flow strives to achieve, we are not comfortable with their flow description language of choice. Namely, they chose to describe page flows in XML. At their heart, page flows are algorithms, and we feel that describing algorithms in a first-class imperative programming language is a more natural fit for the task. It gives you the full expressive power of if, for, switch, etc. statements as well as the ability to define functions and call them from multiple places in the flow, reusing common functionality. JavaScript is close enough in syntax to Java and is easy to learn. To efficiently edit Spring Web Flow flows, you need to hand craft their XML files, a task that looks complex enough that the Spring community started developing graphical editors for maintaining flowgraph XML documents in response to the complexity. In contrast, you can edit a JavaScript web flow in any text editor you'd otherwise find fit for writing a snippet of JavaScript in.

So, it boils down to a matter of having more than one choice if you want to develop web applications with Spring. If you're comfortable with flows expressed in XML, and eventually being forced to use graphical IDE graph builders to describe control flow of a program, use Spring Web Flow, may it do ya fine. If you prefer writing the same control flow in a proper programming language, you might discover JavaScript Web Flow for Spring is right for you.

By using continuations, the state of your script is recorded in an encapsulation of its call stack (together with all local variables) whenever it sends back a HTTP response. Not only does it allow you to store state between two requests simply in script local variables, it also opens up quite wild possibilities. Namely, the users of your web application can navigate at will in your web application: use the back button of their browser few times then continue from there, or even open a new window at a backed page and diverge in two different directions. Your web application will seamlessly assume the script states appropriate for the current page on the next request, as those states aren't thrown away (well, up to a point - by default 100 states are remembered per session). And remember that you only had to write a single, structured, mostly linear script for all of this! The system manages the mapping of user's unpredictable browsing behaviors to your structured-programming script for you!

At the moment, continuations can be stored in-memory, bound to a HTTP session, persisted to a JDBC data source, or persisted into a hidden form field in the generated HTML pages (with support for optional encryption, compression, and digital signing). In the latter two cases, smart stubbing of shared objects is employed that both minimizes the size of the serialized state and allows continuations to be resumed in a different JVM than the one that originally created them, allowing for clustering and failover scenarios. An extensible architecture allows you to develop your own persistence mechanisms as well.

Getting started


You are expected to be familiar with Spring MVC and JavaScript.

An example

The distribution contains a simple example web application that has two flows defined in JavaScript, one of them emulating a checkout process from a web store, and another that implements a tape calculator. Just drop the example into a servlet container of your choice, and point your browser to either "checkout.js" or "calculator.js" inside of it.


JavaDoc will explain you why is the example configured as it is. Especially pay attention to FlowController.handleRequestInternal(HttpServletRequest, HttpServletResponse) which describes the features available to your flowscripts as well as how to incorporate the state ID into HTML pages generated by your views.


There is also a short tutorial available.

Other players in the space

We already mentioned the Spring's default Spring Web Flow implementation. Apache Coccoon also has a web flow engine based on Rhino, but that engine would probably be hard to integrate into Spring proper.