Upgrade to Hibernate 4

This change upgrades Spring Web Flow to Hibernate 4 but remains
compatible with Hibernate 3.

Issue: SWF-1534
This commit is contained in:
Rossen Stoyanchev
2014-02-09 17:45:04 -05:00
parent c32a2e238a
commit ec83f86d9f
5 changed files with 72 additions and 31 deletions

View File

@@ -56,7 +56,7 @@ configure(subprojects.findAll {it.name != "spring-js-resources"}) { subproject -
}
subproject.ext {
springVersion = "4.0.0.RELEASE"
springVersion = "4.0.1.RELEASE"
springSecurityVersion = "3.2.0.RELEASE"
slf4jVersion = "1.6.1"
log4jVersion = "1.2.15"
@@ -132,10 +132,10 @@ project("spring-js") {
compile("org.springframework:spring-web:$springVersion")
compile("org.springframework:spring-webmvc:$springVersion")
provided("javax.servlet:javax.servlet-api:3.0.1")
optional("org.apache.tiles:tiles-api:2.1.2")
optional("org.apache.tiles:tiles-core:2.1.2")
optional("org.apache.tiles:tiles-jsp:2.1.2")
optional("org.apache.tiles:tiles-servlet:2.1.2")
optional("org.apache.tiles:tiles-api:2.2.2")
optional("org.apache.tiles:tiles-core:2.2.2")
optional("org.apache.tiles:tiles-jsp:2.2.2")
optional("org.apache.tiles:tiles-servlet:2.2.2")
testCompile("javax.servlet:jstl:1.2")
testCompile("log4j:log4j:$log4jVersion") {
exclude group: "javax.mail", module: "mail"
@@ -143,6 +143,8 @@ project("spring-js") {
exclude group: "com.sun.jdmk", module: "jmxtools"
exclude group: "com.sun.jmx", module: "jmxri"
}
testCompile("org.slf4j:jcl-over-slf4j:$slf4jVersion")
testCompile("org.slf4j:slf4j-api:$slf4jVersion")
testCompile("org.springframework:spring-test:$springVersion")
}
}
@@ -166,7 +168,7 @@ project("spring-webflow") {
provided("javax.portlet:portlet-api:2.0")
provided("junit:junit:3.8.2")
provided("org.eclipse.persistence:javax.persistence:2.0.0")
optional("org.hibernate:hibernate-core:3.6.9.Final") {
optional("org.hibernate:hibernate-core:4.2.8.Final") {
exclude group: "org.slf4j", module: "slf4j-api"
}
optional("org.slf4j:slf4j-api:$slf4jVersion")
@@ -175,8 +177,8 @@ project("spring-webflow") {
optional("org.springframework:spring-tx:$springVersion")
optional("org.springframework:spring-webmvc-portlet:$springVersion")
testCompile("javax.validation:validation-api:1.0.0.GA")
testCompile("org.hibernate:hibernate-core:3.6.9.Final")
testCompile("org.hibernate:hibernate-entitymanager:3.6.9.Final")
testCompile("org.hibernate:hibernate-core:4.2.8.Final")
testCompile("org.hibernate:hibernate-entitymanager:4.2.8.Final")
testCompile("org.hibernate:hibernate-validator:4.3.0.Final")
testCompile("org.apache.tomcat:tomcat-jasper-el:7.0.27")
testCompile("org.hsqldb:hsqldb:2.2.8")

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2012 the original author or authors.
* Copyright 2004-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,16 +15,21 @@
*/
package org.springframework.webflow.persistence;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.hibernate.FlushMode;
import org.hibernate.Interceptor;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.orm.hibernate4.SessionHolder;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.definition.FlowDefinition;
@@ -48,7 +53,7 @@ import org.springframework.webflow.execution.RequestContext;
* <li>When an existing flow ends, commit the changes made to the session in a transaction if the ending state is a
* commit state. Then, unbind the context and close it.
* </ul>
*
*
* The general data access pattern implemented here is:
* <ul>
* <li>Create a new persistence context when a new flow execution with the 'persistenceContext' attribute starts
@@ -57,7 +62,7 @@ import org.springframework.webflow.execution.RequestContext;
* <li>On successful flow completion, commit and flush those edits to the database, applying a version check if
* necessary.
* </ul>
*
*
* <p>
* Note: All data access except for the final commit will, by default, be non-transactional. However, a flow may call
* into a transactional service layer to fetch objects during the conversation in the context of a read-only system
@@ -68,13 +73,23 @@ import org.springframework.webflow.execution.RequestContext;
* want intermediate flushing to happen, as the nature of a flow implies a transient, isolated resource that can be
* canceled before it ends. Generally, the only time a read-write transaction should be started is upon successful
* completion of the conversation, triggered by reaching a 'commit' end state.
*
*
* @author Keith Donald
* @author Juergen Hoeller
* @author Ben Hale
*/
public class HibernateFlowExecutionListener extends FlowExecutionListenerAdapter {
private static final boolean hibernate3Present = ClassUtils.isPresent("org.hibernate.connection.ConnectionProvider",
HibernateFlowExecutionListener.class.getClassLoader());
private static final Method openSessionMethod =
ReflectionUtils.findMethod(SessionFactory.class, "openSession");
private static final Method openSessionWithInterceptorMethod =
ReflectionUtils.findMethod(SessionFactory.class, "openSession", Interceptor.class);
/**
* The name of the attribute the flow {@link Session persistence context} is indexed under.
*/
@@ -183,8 +198,33 @@ public class HibernateFlowExecutionListener extends FlowExecutionListenerAdapter
}
private Session createSession(RequestContext context) {
Session session = (entityInterceptor != null ? sessionFactory.openSession(entityInterceptor) : sessionFactory
.openSession());
Session session;
if (entityInterceptor != null) {
if (hibernate3Present) {
try {
session = (Session) openSessionWithInterceptorMethod.invoke(sessionFactory, entityInterceptor);
} catch (IllegalAccessException ex) {
throw new IllegalStateException("Unable to open Hibernate 3 session", ex);
} catch (InvocationTargetException ex) {
throw new IllegalStateException("Unable to open Hibernate 3 session", ex);
}
} else {
session = sessionFactory.withOptions().interceptor(entityInterceptor).openSession();
}
} else {
if (hibernate3Present) {
try {
session = (Session) openSessionMethod.invoke(sessionFactory);
} catch (IllegalAccessException ex) {
throw new IllegalStateException("Unable to open Hibernate 3 session", ex);
} catch (InvocationTargetException ex) {
throw new IllegalStateException("Unable to open Hibernate 3 session", ex);
}
}
else {
session = sessionFactory.openSession();
}
}
session.setFlushMode(FlushMode.MANUAL);
return session;
}
@@ -198,7 +238,9 @@ public class HibernateFlowExecutionListener extends FlowExecutionListenerAdapter
}
private void bind(Session session) {
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
Object sessionHolder = (hibernate3Present ?
new org.springframework.orm.hibernate3.SessionHolder(session) : new SessionHolder(session));
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
}
private void unbind(Session session) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2012 the original author or authors.
* Copyright 2004-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,14 +15,11 @@
*/
package org.springframework.webflow.persistence;
import java.sql.SQLException;
import javax.sql.DataSource;
import junit.framework.TestCase;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.core.io.ClassPathResource;
@@ -31,10 +28,10 @@ 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.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.springframework.orm.hibernate4.HibernateCallback;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.webflow.engine.EndState;
import org.springframework.webflow.execution.FlowExecutionException;
@@ -43,7 +40,7 @@ import org.springframework.webflow.test.MockRequestContext;
/**
* Tests for {@link HibernateFlowExecutionListener}
*
*
* @author Ben Hale
*/
public class HibernateFlowExecutionListenerTests extends TestCase {
@@ -86,7 +83,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
assertSessionBound();
hibernateTemplate.executeWithNativeSession(new HibernateCallback<Object>() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
public Object doInHibernate(Session session) {
assertSame("Should have been original instance", hibSession, session);
return null;
}

View File

@@ -6,8 +6,8 @@ import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.webflow.execution.Action;
import org.springframework.webflow.execution.Event;

View File

@@ -5,9 +5,9 @@ import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.webflow.execution.FlowExecutionListener;