Enterprise Java Community: Implementing Finite State Machines with Physhun and Spring

来源:百度文库 编辑:神马文学网 时间:2024/04/29 00:07:12
<a href=‘http://ad.doubleclick.net/jump/atssc/tt_articles;bkg=FFFFFF;kw=;dcopt=;pos=1;sz=125x100;ptile=1;ord=2748652?‘‘> <img src=‘http://ad.doubleclick.net/ad/atssc/tt_articles;bkg=FFFFFF;kw=;dcopt=;pos=1;sz=125x100;ptile=1;ord=2748652?‘‘ width=‘125‘ height=‘82‘ border=‘0‘></a>

<a href=‘http://ad.doubleclick.net/jump/atssc/tt_articles;bkg=FFFFFF;kw=;dcopt=;pos=2;sz=125x100;ptile=2;ord=2748652?‘‘> <img src=‘http://ad.doubleclick.net/ad/atssc/tt_articles;bkg=FFFFFF;kw=;dcopt=;pos=2;sz=125x100;ptile=2;ord=2748652?‘‘ width=‘125‘ height=‘82‘ border=‘0‘></a>

<a href=‘http://ad.doubleclick.net/jump/atssc/tt_articles;bkg=FFFFFF;kw=;dcopt=;pos=3;sz=125x100;ptile=3;ord=2748652?‘‘> <img src=‘http://ad.doubleclick.net/ad/atssc/tt_articles;bkg=FFFFFF;kw=;dcopt=;pos=3;sz=125x100;ptile=3;ord=2748652?‘‘ width=‘125‘ height=‘82‘ border=‘0‘></a>

<a href=‘http://ad.doubleclick.net/jump/atssc/tt_articles;bkg=FFFFFF;kw=;dcopt=;pos=4;sz=125x100;ptile=4;ord=2748652?‘‘> <img src=‘http://ad.doubleclick.net/ad/atssc/tt_articles;bkg=FFFFFF;kw=;dcopt=;pos=4;sz=125x100;ptile=4;ord=2748652?‘‘ width=‘125‘ height=‘82‘ border=‘0‘></a>

Resources
Enterprise JavaResearch Library
Get Java white papers, product information, case studies and webcasts
<a href=‘http://ad.doubleclick.net/jump/atssc/tt_articles;bkg=FFFFFF;kw=;dcopt=;pos=1;sz=120x600;ptile=1;ord=2748652?‘‘> <img src=‘http://ad.doubleclick.net/ad/atssc/tt_articles;bkg=FFFFFF;kw=;dcopt=;pos=1;sz=120x600;ptile=1;ord=2748652?‘‘ width=‘120‘ height=‘600‘ border=‘0‘></a>


July 18, 2008
Discuss this Article
Abstract
When software is required to solve complex problems, the propersolutions are often beyond the capabilities of traditional programming techniques.A robust alternative for solving very complex problems is to use the FiniteState Machine (FSM) paradigm for modeling the solution space and a FSM-basedframework for the implementation. This paper presents the Physhun project,a Spring-based framework for implementing complex processes through FiniteState Machine models. Physhun provides finite State Model persistence and transactionmanagement with synchronous or asynchronous behavior. Although developmentwith Physhun can be accomplished much more quickly and efficiently with PhyshunModeler, we will demonstrate development without Modeler to give visibilityinto the Physhun framework.
Finite State Machines and Process Control
Complex process logic is common in information systems. Itcan be found in software ranging from GUIs to Operational Support Systems.There are many concise ways of describing complex processes, the most commonbeing flow charts and UML diagrams; however, implementation of complex processesmay not always be as straightforward. Complex processes are often implementedas procedural logic which can become lengthy and difficult to manage as processrules change.
A complementary technology toprocedural and object-oriented programming is the Finite State Machine paradigm.Finite State Machine (FSM) is a behavioral algorithm that can be used to modeland execute complex logic. A finite state machine defines a process as a setof states (nodes) and state Transitions (edges). Implementation of a processwith FSM technology involves laying out the valid states for the process, allTransitions between those states, Conditions dictating when Transitions areto be executed and Actions containing logic to be executed on Transition execution.
Finite state machine technology has been used for a numberof years in a wide spectrum of industries. Successful projects using finiteState Model technology include communication systems, automobiles, avionicssystems, and man-machine interfaces. These problem domains share common characteristics;they are usually complex, large in size and reactive in nature. A primary challengeof these domains is the difficulty of describing reactive behavior in waysthat are clear, concise, and complete while at the same time formal and rigorous.
Finite State Models provide a way to describe large, complexsystems. Finite State Machines view these systems as a set of well definedstates, inbound and outbound events, Conditions, and Actions. FSM technologyprovides a set of rules for evaluating and processing the events, Conditions,and Actions. The partitioning of the problem into the states, events, Conditions,and Actions, the structured processing environment, and the ease of expressingthe processing logic are the foremost strengths of FSMs.
The fundamental components of finite State Models include:
State represents the “mode of being” forthe system at any given time.
Transition describes a single pathway from a stateto another state. The set of all Transitions describe all possible paths amongthe defined states. A Transition contains an event that it is subscribing to(the event that triggers execution of the Transition), a Condition and an Action.A Transition also contains references to the state from which the Transitionis exiting (i.e. the “from” state) and the state to which the Transitionis entering (i.e. the “to” state).
Event is the mechanism that the system uses to interactwith external systems and with itself.
Condition represents a set of logic that evaluatesto a Boolean result. A Condition is used to determine if a Transition is tobe executed.
Action is the logic to be executed when a Transitionis executed.
A diagram of the components of a typical FSMis shown below:

Illustration 1: State Model Core Components
Physhun Overview
Physhun is an open source framework for building and executingFinite State Machines in J2SE and J2EE environments. Although the frameworkis simple, it is powerful in that it allows processes to be long lived, persistentand transactional. Processes can be purely synchronous or asynchronous. Synchronousprocesses once started, will run to completion without any further interactionfrom outside systems or users. Asynchronous processes will have states thatrequire input from external systems or users before the process will continue.Asynchronous behavior is common in workflow systems.
The Physhun framework leverages the Spring framework and exposesall of the value added services provided by Spring including Inversion of Control(IOC), Aspect-Oriented Programming (AOP) and transaction management. Physhunallows the usage of graphical editors such as Physhun Modeler for developmentof State Models. This allows for accelerated development, ease of maintenanceand facilitated communication.
Process control with Physhun is accomplished by defining processesas State Models. A State Model is defined as a JavaBean comprised of the followingcomponents:
States (com.wazeegroup.physhun.framework.State)
Transitions (com.wazeegroup.physhun.framework.Transition)
Actions (com.wazeegroup.physhun.framework.Action)
Conditions (com.wazeegroup.physhun.framework.Condition)
A State model can be defined in one of several ways. The firstway is to define the beans comprising the State Model in Java code. The secondway is to define the State Model as XML that can be consumed by a bean factory(such as one of those provided by the Spring framework). The third way is todefine the State Model graphically using an editor like Physhun Modeler. Definingthe State Model graphically is appealing because it allows a complex processto be easily understood, communicated and maintained. In all three of thesemethods the elements comprising the State Model are defined and wired togetheras Spring beans and can be written to take advantage of Spring services.
The Physhun runtime paradigm is this: A process is definedby a process model. Multiple instances of a given process can be executed.Each process instance has a business object (ProcessObject) instance associatedwith it, which traverses a State Model. The data in the ProcessObject can beused to determine which paths in the State Model to take (via execution ofConditions). As the process executes, Actions in the State Model may manipulatethe ProcessObject.
Physhun processes are instantiated and interacted with atruntime through a ProcessContainer. The ProcessContainer interface is shownin Table1. It contains methods for starting processes and sending asynchronousevents to existing processes. Executing Physun State Models is as simple asinstantiating a ProcessObject and passing it to the Physun ProcessContainerinstance.
package com.wazeegroup.physhun.engine;import com.wazeegroup.physhun.framework.ProcessObject;import com.wazeegroup.physhun.framework.StateModel;public interface ProcessContainer {public void startProcess(ProcessObject processObject, StateModel stateModel);public ProcessObject sendTriggerEventToProcess(String processID, Object triggerEvent);public void resumeProcess(ProcessObject processObject, StateModel stateModel);}
Table 1: ProcessContainer interface
The low-level rules for how State Models are executed aredefined in the StateEngine. Generally, the developer does not need to interactwith the StateEngine directly, but through the ProcessContainer which willproxy calls to the StateEngine appropriately. Physhun provides standard implementationsfor ProcessContainer and StateEngine, but the user may define and use differentimplementations as the need arises.
For long lived and mission critical processes, the Physhunlibrary provides the ability to persist ProcessObjects, suspend and resumelong lived processes and tie process execution into distributed transactions.
Example 1: Simple process control
In this example, we will build an overly simplified orderprocess. The order process is this: Order received, check inventory, if theproduct is not in stock cancel the order. Otherwise, complete the order.

Illustration 2: Simple Example Process Model
The first step in the implementation is to define a ProcessObject.This is the object that will traverse the State Model during process execution.Other FSM technologies may refer to the object as a Business Object, BusinessProcess Object (BPO) or Process Document. The ProcessObject implementationmust implement the interface com.wazeegroup.Physhun.framework.IProcessObject.The ProcessObject for this example is defined by the class com.wazeegroup.physhun.examples.simple.Order,which is shown in Table2.
package com.wazeegroup.physhun.examples.simple;import com.wazeegroup.physhun.framework.ConcreteProcessObject;public class Order extends ConcreteProcessObject {private String customerId;private String itemId;public int quantity;public Order(String customerId, String itemId, int quantity) {super(null);this.customerId = customerId;this.itemId = itemId;this.quantity = quantity;setID(toString());}public String toString() {return ("Order (" + customerId + "/" + itemId + "/" + quantity + " units)");}}
Table 2: A simple ProcessObjectimplementation
Note that Order inherits from com.wazeegroup.Physhun.framework.ConcreteProcessObject.By inheriting from this concrete class, we are saved from the effort of implementing “plumbing” functionalitysuch as tracking current state and other details allow the ProcessObject tofunction in the Physhun StateEngine.
The next step is to define the State Model for the order process.A visual representation of the model is shown in Illustration2. The State Model is a spring bean made up of States and Transitions andis easily defined as an XML document. The XML defining the State Model is shownin Table3. This XML document can be consumed by a Spring bean factory to inflatethe State Model as Java objects. The State Model definition is lengthy, butit is straightforward and easy to understand, especially when viewed with agraphical editor.
Once the ProcessObject and State Model have been defined,any custom Actions and Conditions must be implemented. Conditions define thecircumstances that must be met for a Transition from one state to another tooccur. At runtime the StateEngine evaluates Conditions to determine what Transition(if any) to execute. Actions define the logic that is executed on a given Transition.The code for a simple Condition is shown in Table4 and an Action in Table5.
truetruetrue
Table 3: State Model XML
package com.wazeegroup.physhun.examples.simple;import com.wazeegroup.physhun.framework.AbstractCondition;import com.wazeegroup.physhun.framework.ProcessObject;import java.util.Random;public class CheckOrderAvailability extends AbstractCondition {private static final Random _random = new Random();public boolean evaluate(ProcessObject iProcessObject) {boolean result = _random.nextBoolean();System.out.println("Order Availability for Order (" + iProcessObject + "): " + result);return result;}}
Table 4: A simple Conditionimplementation
package com.wazeegroup.physhun.examples.simple;import com.wazeegroup.physhun.framework.AbstractAction;import com.wazeegroup.physhun.framework.ProcessObject;public class CommitOrder extends AbstractAction {public void execute(ProcessObject iProcessObject) {System.out.println(iProcessObject + " - completed");}}
Table 5: A simple Action implementation
Now that the State Model, ProcessObject, Actions and Conditionshave been defined, the final step is to load and execute the process. To executethe process, two additional components are needed: A StateEngine and a ProcessContainer.The StateEngine is the component that contains the rules on how State Modelsexecuted, and the ProcessContainer is the component that keeps track of processinstances and sends events to those instances. The default StateEngine is com.wazeegroup.Physhun.engine.StandardEngine,and the default ProcessContainer is com.wazeegroup.physhun.SimpleProcessContainer.The ProcessContainer and StateEngine are configured by standard Spring configurationas shown in Table6. The code used to execute the example is shown in Table7.

Table 6: Sample ProcessContainerconfiguration
package com.wazeegroup.physhun.examples.simple;import com.wazeegroup.physhun.engine.ProcessContainer;import com.wazeegroup.physhun.framework.StateModel;import org.springframework.context.support.ClassPathXmlApplicationContext;public class RunSample {public static void main(String[] args) {if (args.length < 3) {System.err.println("usage: RunSample custID itemID numItems");} else {Order order = new Order(args[0], args[1], Integer.parseInt(args[2]));//Get the Spring ApplicationContextString[] beanFiles = new String[]{"simple-processConfig.xml", "simple-stateModel.xml"};ClassPathXmlApplicationContext ctx =new ClassPathXmlApplicationContext(beanFiles);//inflate and retrieve the ProcessContainer bean.ProcessContainer container = (ProcessContainer) ctx.getBean("ProcessContainer");//inflate and retrieve the stateModel bean.StateModel stateModel = (StateModel) ctx.getBean("stateModel");container.startProcess(order, stateModel);}}}
Table 7: Execution of the StateModel
Example 2: Long Lived Processes and Asynchronous Events
Our first example showed a very simple order management process.In that example, the process is short lived and synchronous – as soonas the process is started, it runs to completion without dependence on incomingevents. The second example is similar to the first, but with added asynchronousbehavior – in this example, the process waits for and reacts to asynchronousevents indicating changes to inventory. When the order is created, if stockis available to fill the order, the order completes normally. Otherwise, theprocess waits until it receives notification that the appropriate inventoryis available at which point the process is completed. The new State Model isshown in Illustration3.

Illustration 3: Asynchronous process State Model
The Transitions from the waitForStock state are triggeredby an external event – in this case, notification that inventory changeshave occurred. The Transition from waitForStock to orderComplete occurs ifthe inventory system notifies the process that stock is now available. ThewaitForStock self-Transition occurs if an inventory change occurs that doesnot result in appropriate stock being available. In order to define an “asynchronous” Transition,we associate a TriggeredCondition with the Transition. A TriggeredConditionimplements the interface com.wazeegroup.physhun.framework.TriggeredConditionand is very similar to Condition, the difference being that the evaluate()method takes an additional Object which is the asynchronous event that drivesthe Transition. The TriggeredCondition implementation for this example is showninTable8, and the Condition and Transition definitions from the State Model XMLare shown in Table9.
package com.wazeegroup.physhun.examples.asynch;import com.wazeegroup.physhun.framework.AbstractTriggeredCondition;import com.wazeegroup.physhun.framework.ProcessObject;public class InventoryChanged_orderStockAvailable extends AbstractTriggeredCondition {public boolean evaluate(ProcessObject processObject, Object triggerEvent) {InventoryChangeEvent evt = (InventoryChangeEvent)triggerEvent;System.out.println("Received inventory change event (" + evt.itemID + "/" + evt.newQuantity + " units)");Order order = (Order)processObject;if (evt.itemID.equals(order.getItemId()) && evt.newQuantity >= order.getQuantity()) {//the item we are waiting on is now in stock.System.out.println("Item we are waiting for is now in stock. Condition evaluates to true!");return true;}else {//We still don‘t have enough stock to fill the orderSystem.out.println("Inventory we are waiting for(" + order.getQuantity() + " units of " + order.getItemId() + ")is still out of stock");return false;}}}
Table 8: TriggeredConditionimplementation

Table 9: Asynchronous Transitionand Condition State Model definition
In this example, the asynchronous event that drives Transitionsfrom the waitForStock state are notifications of changes to inventory. In anenterprise system, these may be anything from calls to a Web Service to eventspublished on a JMS destination, event queue or other Enterprise Message Bus.
The final step is to bridge the asynchronous events into therunning process. This is done via the ProcessContainer by calling the methodsendTriggerEventToProcess(). In our example, we mock up inventory change eventsby spawning a thread that sends mocked up inventory change events to the ProcessContainer.The code used to execute this example and send asynchronous events to the processinstances is shown in Table10.
package com.wazeegroup.physhun.examples.asynch;import com.wazeegroup.physhun.engine.ProcessContainer;import com.wazeegroup.physhun.framework.StateModel;import org.springframework.context.support.ClassPathXmlApplicationContext;import java.util.Random;public class RunSample {public static void main(String[] args) {if (args.length < 3) {System.err.println("usage: RunSample custID itemID numItems");} else {Order order = new Order(args[0], args[1], Integer.parseInt(args[2]));ClassPathXmlApplicationContext ctx = newClassPathXmlApplicationContext(new String[]{"asynch-processConfig.xml","asynch-stateModel.xml"});ProcessContainer container = (ProcessContainer) ctx.getBean("ProcessContainer");//inflate and retrieve the ProcessContainer bean.StateModel stateModel = (StateModel) ctx.getBean("stateModel");//inflate and retrieve the stateModel bean.InventorySystemStub stub = new InventorySystemStub();stub.container = container;stub.orderID = order.getID();stub.start();container.startProcess(order, stateModel);while (! stateModel.isProcessComplete(order)) {try { Thread.sleep(50); } catch (InterruptedException ie) {}}stub.finished = true;stub.interrupt();}}}class InventorySystemStub extends Thread {public boolean finished = false;public String orderID;public ProcessContainer container;public String[] itemIDs = new String[] {"RootBeer", "CremeSoda", "Lollipops", "LicorishWhips"};public void run() {Random random = new Random();try { Thread.sleep(5000); } catch (InterruptedException ie) {}while (!finished) {InventoryChangeEvent event = new InventoryChangeEvent();event.itemID = itemIDs[random.nextInt(itemIDs.length)];event.newQuantity = random.nextInt(100);container.sendTriggerEventToProcess(orderID, event);try { Thread.sleep(5000); } catch (InterruptedException ie) {}}}}
Table 10: Execution of the AsynchronousState Model
Example 3: Distributed Transactions and ProcessObject Persistence
In the final example, we add a distributed transaction andProcessObject persistence to our process. ProcessObject persistence writesthe state of the process to a datastore. This is important for two reasons:it allows data to be restored in the event of a system failure, and it allowsthe construction large scale systems. Systems can run with many concurrentprocesses without keeping all Process Instances in memory at all times.
The process in this example is identical to the process inExample 2, but we change the commitOrder Action (which is the Action associatedwith the Transition from waitForStock to orderComplete) to do the following:reserve inventory in the inventory system, enter the order in the billing systemand enter the order in the provisioning system. All three of these steps areexecuted against different systems, but must be done as a single transaction.For this example, our interface to each of the target systems is through thedatabase. To accomplish this distributed transaction, we must do three thingsin our implementation:
Code individual Actions to work with a common transaction manager. To accomplish this, we wire an appropriately configured DataSource object in to each Action, and modify the Actions to acquire DB connectivity through the DataSource.
Configure a Spring transaction manager and wire it into the StateEngine and DataSource beans.
Define a composite Action that aggregates the individual Actions that make up the distributed transaction.
The XML for the composite Action is shown in Table11 and a representative Action class implementation is shown in Table12. Note that each of the Actions use a DataSource. The DataSources arestandard Spring JDBC DataSources with a common TransactionManager wired in.That same TrasnactionManager is also wired in to the Physhun StateEngine.The code in the Actions is simple; it uses the DataSource to aquire a DBconnection, through which it manipulates data.

Table 11: Composite Action definitionfor a distributed transaction
package com.wazeegroup.physhun.examples.transactional;import com.wazeegroup.physhun.framework.ProcessObject;import com.wazeegroup.physhun.framework.PhyshunException;import com.wazeegroup.physhun.framework.AbstractAction;import javax.sql.DataSource;import org.springframework.jdbc.core.JdbcTemplate;import java.sql.Types;public class ReserveInventory extends AbstractAction {private DataSource dataSource;private JdbcTemplate _jdbcTemplate;public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;_jdbcTemplate = new JdbcTemplate(dataSource);}public void execute(ProcessObject processObject) {try {Order order = (Order)processObject;_jdbcTemplate.update("update inventory set quantity = quantity-? where item_id = ?",new Object[]{new Integer(order.getQuantity()), order.getItemId()},new int[]{Types.INTEGER, Types.VARCHAR});} catch (Exception e) {throw new PhyshunException("Error during execute", e);}}}
Table 12: Implementation ofAction class that is used in a distributed transaction
Note that ProcessObject persistence does not necessarily haveto be implemented from scratch. The PhyshunXML package provides a ProcessObjectimplementation whose data is all stored internally in an XML Document. Thispackage also provides persistence functionality to Oracle and MySQL databases.If desired, implementation of custom persistence is straightforward. For thesake of illustration this example demonstrates implementation of custom ProcessObjectand persistence functionality.
To add ProcessObject persistence, we must do two things:
Define a ProcessObjectPersistence class. This is where we define how to store and retrieve the ProcessObject to and from the persistence layer.
Wire the ProcessObjectPersistence class defined in step 1 into the StateEngine.
When the StateEngine has a ProcessObjectPersistence objectwired in, it will persist the ProcessObject on execution of each state Transition.Furthermore, if the StateEngine has a Transaction Manager wired in, it willpersist the ProcessObject as part of the state Transition transaction. Thistransaction includes persistence of the ProcessObject and execution of anyActions associated with the Transition The example ProcessObjectPersistenceclass is shown in Table13 and the Container and StateEngine XML are shown in Table14.
Note that the StateEngine and DataSources for Billings, Warehouse,Inventory and Orders (ProcessObject persistence store) databases all use thesame TransactionManager. Because the beans are wired in this manner, when theStateEngine executes a Transition, persistence of the ProcessObject and Actionson the transition will be executed on the same transaction. So, if a singleAction, or persistence of the ProcessObject fails, the entire transaction willfail as a whole and no data will be written to any of the data sources. TheTransition will be rolled back and the process will roll back to the statefrom which the Transition occurred.
package com.wazeegroup.physhun.examples.transactional;import com.wazeegroup.physhun.framework.ProcessObjectPersistenceSupport;import com.wazeegroup.physhun.framework.ProcessObject;import javax.sql.DataSource;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowCallbackHandler;import java.sql.Types;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;public class OrderPersistenceSupport implements ProcessObjectPersistenceSupport {private DataSource dataSource;private JdbcTemplate _jdbcTemplate;public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;_jdbcTemplate = new JdbcTemplate(dataSource);}public void persistState(ProcessObject obj) {Order order = (Order)obj;Address shipTo = order.getShippingAddress();_jdbcTemplate.update("delete from orders where order_id = ?", new Object[] { order.getID() },new int[] { Types.VARCHAR });_jdbcTemplate.update("insert into orders values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",new Object[] { order.getID(),order.getActiveStates()[0], order.getItemId(), new Integer(order.getQuantity()),order.getCustomerId(), shipTo.getStreet1(), shipTo.getStreet2(), shipTo.getCity(),shipTo.getState(), shipTo.getZip() },new int[] { Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.VARCHAR,Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR });}public ProcessObject getPersistedObject(final String id) {final ArrayList resultsList = new ArrayList();_jdbcTemplate.query("select item_id, process_state, quantity, customer_id, shipping_street1,shipping_street2, " + "shipping_city, shipping_state, shipping_zip from orders whereorder_id = ?", new Object[] {id},new int[] { Types.VARCHAR },new RowCallbackHandler() {public void processRow(ResultSet resultSet) throws SQLException {Order order = new Order(null);order.setID(id);order.setCustomerId(resultSet.getString("customer_id"));order.setItemId(resultSet.getString("item_id"));order.setQuantity(resultSet.getInt("quantity"));Address addr = new Address();addr.setStreet1(resultSet.getString("shipping_street1"));addr.setStreet2(resultSet.getString("shipping_street2"));addr.setCity(resultSet.getString("shipping_city"));addr.setState(resultSet.getString("shipping_state"));addr.setZip(resultSet.getString("shipping_zip"));order.setShippingAddress(addr);String activeState = resultSet.getString("process_state");order.setStateActive(activeState);resultsList.add(order);}});if (resultsList.size() < 1) {System.err.println("Order (" + id + ") not found in DB");return null;}else if (resultsList.size() == 1) {return resultsList.get(0);}else {throw new RuntimeException("Multiple orders with id (" + id + ") found in DB");}}public ProcessObject[] getPersistedObjects() {//not used in this example, but normally this should be implemented.return null;}}
Table 13: ProcessObjectPersistenceSupportimplementation
${inventory.driver}${inventory.url}${inventory.username}${inventory.password}2${billing.driver}${billing.url}${billing.username}${billing.password}2${warehouse.driver}${warehouse.url}${warehouse.username}${warehouse.password}2${orders.driver}${orders.url}${orders.username}${orders.password}2
Table 14: XML definitions forStateEngine and supporting beans
Conclusion
Finite State Machine technology offers a useful, alternativeparadigm to implementing complex logic and process flow. The Physhun projectis an open source framework that enables rapid development of systems usingFinite State Machine technology, while leveraging and exposing the power andflexibility of the Spring Framework. More information about the Physhun project,including examples, source code and binaries can be found on the Physhun projecthomepage athttp://physhun.sourceforge.net.