package org.springframework.webflow.persistence;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import junit.framework.TestCase;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.webflow.engine.EndState;
import org.springframework.webflow.execution.FlowExecutionException;
import org.springframework.webflow.test.MockFlowSession;
import org.springframework.webflow.test.MockRequestContext;
@SuppressWarnings("deprecation")
public class JpaFlowExecutionListenerTests extends TestCase {
private EntityManagerFactory entityManagerFactory;
private JpaFlowExecutionListener jpaListener;
private JdbcTemplate jdbcTemplate;
public void testTemp() {
}
protected void setUp() throws Exception {
DataSource dataSource = getDataSource();
populateDataBase(dataSource);
jdbcTemplate = new JdbcTemplate(dataSource);
entityManagerFactory = getEntityManagerFactory(dataSource);
JpaTransactionManager tm = new JpaTransactionManager(entityManagerFactory);
jpaListener = new JpaFlowExecutionListener(entityManagerFactory, tm);
}
public void testFlowNotAPersistenceContext() {
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
jpaListener.sessionStarting(context, flowSession, null);
assertSessionNotBound();
}
public void testFlowCommitsInSingleRequest() {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
jpaListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
TestBean bean = new TestBean(1, "Keith Donald");
EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
em.persist(bean);
assertEquals("Table should still only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
EndState endState = new EndState(flowSession.getDefinitionInternal(), "success");
endState.getAttributes().put("commit", true);
flowSession.setState(endState);
jpaListener.sessionEnding(context, flowSession, "success", null);
jpaListener.sessionEnded(context, flowSession, "success", null);
assertEquals("Table should only have two rows", 2, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
assertSessionNotBound();
}
public void testFlowCommitsAfterMultipleRequests() {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
jpaListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
TestBean bean1 = new TestBean(1, "Keith Donald");
EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
em.persist(bean1);
assertEquals("Table should still only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
jpaListener.paused(context);
assertSessionNotBound();
jpaListener.resuming(context);
TestBean bean2 = new TestBean(2, "Keith Donald");
em = EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
em.persist(bean2);
assertEquals("Table should still only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
assertSessionBound();
EndState endState = new EndState(flowSession.getDefinitionInternal(), "success");
endState.getAttributes().put("commit", true);
flowSession.setState(endState);
jpaListener.sessionEnding(context, flowSession, "success", null);
jpaListener.sessionEnded(context, flowSession, "success", null);
assertEquals("Table should only have three rows", 3, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
assertSessionNotBound();
}
public void testCancelEndState() {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
jpaListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
TestBean bean = new TestBean(1, "Keith Donald");
EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
em.persist(bean);
assertEquals("Table should still only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
EndState endState = new EndState(flowSession.getDefinitionInternal(), "cancel");
endState.getAttributes().put("commit", false);
flowSession.setState(endState);
jpaListener.sessionEnding(context, flowSession, "cancel", null);
jpaListener.sessionEnded(context, flowSession, "success", null);
assertEquals("Table should only have two rows", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
assertSessionNotBound();
}
public void testNoCommitAttributeSetOnEndState() {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
jpaListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
EndState endState = new EndState(flowSession.getDefinitionInternal(), "cancel");
flowSession.setState(endState);
jpaListener.sessionEnding(context, flowSession, "cancel", null);
jpaListener.sessionEnded(context, flowSession, "success", null);
assertEquals("Table should only have three rows", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
assertSessionNotBound();
}
public void testExceptionThrown() {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
jpaListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
TestBean bean = new TestBean(1, "Keith Donald");
EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
em.persist(bean);
assertEquals("Table should still only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
jpaListener.exceptionThrown(context, new FlowExecutionException("bla", "bla", "bla"));
assertEquals("Table should still only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
assertSessionNotBound();
}
public void testExceptionThrownWithNothingBound() {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
assertSessionNotBound();
jpaListener.exceptionThrown(context, new FlowExecutionException("foo", "bar", "test"));
assertSessionNotBound();
}
private DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:mem:jpa");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
private void populateDataBase(DataSource dataSource) throws Exception {
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
databasePopulator.addScript(new ClassPathResource("test-data.sql", this.getClass()));
DataSourceInitializer initializer = new DataSourceInitializer();
initializer.setDataSource(dataSource);
initializer.setDatabasePopulator(databasePopulator);
initializer.afterPropertiesSet();
}
private EntityManagerFactory getEntityManagerFactory(DataSource dataSource) throws Exception {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource);
factory.setPersistenceXmlLocation("classpath:org/springframework/webflow/persistence/persistence.xml");
factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factory.afterPropertiesSet();
return factory.getObject();
}
private void assertSessionNotBound() {
assertNull(TransactionSynchronizationManager.getResource(entityManagerFactory));
}
private void assertSessionBound() {
assertNotNull(TransactionSynchronizationManager.getResource(entityManagerFactory));
}
}