This pattern creates a PersistenceContext
in flowScope
on flow startup,
uses that context for data access during the course of flow execution, and commits changes made to persistent entities at the end.
This pattern provides isolation of intermediate edits by only committing changes to the database at the end of flow execution.
This pattern is often used in conjunction with an optimistic locking strategy to protect the integrity of data modified in parallel by multiple users.
To support saving and restarting the progress of a flow over an extended period of time, a durable store for flow state must be used.
If a save and restart capability is not required, standard HTTP session-based storage of flow state is sufficient.
In that case, session expiration or termination before commit could potentially result in changes being lost.
To use the FlowScoped PersistenceContext pattern, first mark your flow as a persistence-context
:
<?xml version="1.0" encoding="UTF-8"?> <flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"> <persistence-context /> </flow>
Then configure the correct FlowExecutionListener
to apply this pattern to your flow.
If using Hibernate, register the HibernateFlowExecutionListener
. If using JPA, register the JpaFlowExecutionListener
.
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry"> <webflow:flow-execution-listeners> <webflow:listener ref="jpaFlowExecutionListener" /> </webflow:flow-execution-listeners> </webflow:flow-executor> <bean id="jpaFlowExecutionListener" class="org.springframework.webflow.persistence.JpaFlowExecutionListener"> <constructor-arg ref="entityManagerFactory" /> <constructor-arg ref="transactionManager" /> </bean>
To trigger a commit at the end, annotate your end-state with the commit attribute:
<end-state id="bookingConfirmed" commit="true" />
That is it. When your flow starts, the listener will handle allocating a new EntityManager
in flowScope
.
Reference this EntityManager at anytime from within your flow by using the special persistenceContext
variable.
In addition, any data access that occurs using a Spring managed data access object will use this EntityManager automatically.
Such data access operations should always execute non transactionally or in read-only transactions to maintain isolation of intermediate edits.