A finite State Transition Machine (FSTM) is a very useful computing concept. It helps the developer to capture, visualize and code the requisite logic for state management and keep this independent of the actual stuff that happens within a state. It is not my intention here to capture what a state transition machine does. I would defer this to other treatises and instead keep the purview of this article to an implementation of STM that I had committed to sourceforge. In the article below, STM refers to my particular implementation and not the State Transition Machine as a concept.
The need arose when I wanted to develop a simple state machine for maintaining the state of the user as he or she navigates through a series of screens while trying to achieve some functionality in a very complex digital commerce web site. As it often happens, a digital commerce web site's behavior is determined by the state of the user which is a combination of both session characteristics and the navigational path that has been taken by the user so far in his often mindless meanderings around the web site to familiarize himself with its features.
An independent problem arose when a record in a database had to navigate thru a series of states and then had to culminate in either a SUCCESS or ERROR state. Both these independent problems posed different challenges and I was hard pressed to find a simple STM that could cater to all these requirements at a basic level. So I wrote one myself and used it in both these scenarios successfully. I wanted to share this with a wider audience and accordingly made it feature rich.
These represent the different states of the process. Usually represented as a box in the State Transition diagram. In STM, states are represented by state descriptors which contain the information about the state along with its transitions. (see StateDescriptor)
The lines that connect the boxes. These are the ways in which one state can move into another. In STM, transitions are represented using a transition descriptor. (see Transition)
An event triggers the flow from every state. There must exist a transition that corresponds to each event that can be generated at every state. This transition would move the entity forward to the new state. In STM, events are represented as Java Strings
The entity whose state needs to be managed by the STM.
An automatic state is one where the event generated can be determined programatically. Useful for decisions that determine the next state of the entity. E.g: If all items are cancelled, then the order must move to Cancelled state.
The State Transition Diagram is configurable using an XML file that also supports DSL capabilities. This file is typically placed in the class path.(Alternate representations using a DB are also possible)
There are two types of states supported by STM. An automatic state is one where the event generated can be determined programatically. This logic typically resides in a class. In STM, the class must implement the STMAction interface. The STMAction interface uses a generic to cater to different types of flow contexts.
All automatic states must provide an STMAction so that STM can automatically determine the event that needs to be generated for a particular state to transition to the next one. Some states are "pre-shipped" along with STM. These provide common functionality that is typically required. Three of them support scripting and would be discussed in brief here:
If Action : This action helps the developer to implement an IF condition. Consider a particular state (call it 'preApproval' state) where a simple decision from the flow context would suffice to determine what the next transition should be from the current state. Ex: We may want to make all orders with orderTotal < 10000 as "Auto Approved" while orders with total >= 10000 may need to be routed for manual approval. Instead of writing code it is far easier to write a simple script that emits the correct event. IfAction comes handy here.
<if id='preApproval' condition="orderTotal <= 10000" then="Auto Approved" else="Manual Approval"/>
will take care of this problem trivially. Besides, this approach also has the advantage of exposing the logic into the STD rather than in a separate action class which is useful for trivial conditions akin to the above.
Script Action: Script Action provides an alternate way to accomplish the above. In this case, the STD would look like
<script id='preApproval' code='orderTotal <=10000 ? "Auto Approved" : "Manual Approval"'/>
Switch Action: Switch action provides a third way to accomplish the same use case:
<switch id='preApproval' expression='orderTotal <= 10000' case-true='Auto Approved' case-false="Manual Approval"/>
The scripting support serves two purposes:
Scripting support is implemented by using a ScriptingStrategy. Currently, OgnlScriptingStrategy is shipped along with STM. But it is fairly trivial to switch the scripting strategy to something else. Scripting strategy is configured by default in the com/itmusings/stm/impl/stm-conf.xml. However, this can be over ridden by custom strategies.
Manual states are ones where the event Id cannot be automatically computed. It instead requires user intervention in some form. This may be captured using a web form or some user action (such as sending an email). The STM cannot make progress in a manual state. It needs the calling process to re-invoke it with an event Id to make progress. Please see the STM documentation for more detail around this.
Please see theSTM FAQ for more information.