diff -Nru spring-framework-3.2.18.RELEASE/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/ConfigurableJtaPlatform.java spring-framework-3.2.18.RELEASE.hibernate4.3/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/ConfigurableJtaPlatform.java
--- spring-framework-3.2.18.RELEASE/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/ConfigurableJtaPlatform.java	2016-12-21 19:42:08.000000000 +0100
+++ spring-framework-3.2.18.RELEASE.hibernate4.3/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/ConfigurableJtaPlatform.java	2016-12-22 20:34:41.500296971 +0100
@@ -16,60 +16,133 @@
 
 package org.springframework.orm.hibernate4;
 
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
 import javax.transaction.UserTransaction;
 
-import org.hibernate.service.jta.platform.internal.AbstractJtaPlatform;
+import org.hibernate.TransactionException;
+import org.hibernate.service.Service;
 
 import org.springframework.transaction.jta.UserTransactionAdapter;
 import org.springframework.util.Assert;
 
 /**
- * Implementation of Hibernate 4's {@link org.hibernate.service.jta.platform.spi.JtaPlatform}
- * SPI, exposing passed-in {@link TransactionManager} and {@link UserTransaction} references.
+ * Implementation of Hibernate 4's JtaPlatform SPI (which has a different package
+ * location in Hibernate 4.0-4.2 vs 4.3), exposing passed-in {@link TransactionManager},
+ * {@link UserTransaction} and {@link TransactionSynchronizationRegistry} references.
  *
  * @author Juergen Hoeller
  * @since 3.1.2
  */
-@SuppressWarnings("serial")
-class ConfigurableJtaPlatform extends AbstractJtaPlatform {
+@SuppressWarnings({"serial", "unchecked"})
+class ConfigurableJtaPlatform implements InvocationHandler {
+
+	static final Class<? extends Service> jtaPlatformClass;
+
+	static {
+		Class<?> jpClass;
+		try {
+			// Try Hibernate 4.0-4.2 JtaPlatform variant
+			jpClass = SpringSessionContext.class.getClassLoader().loadClass(
+					"org.hibernate.service.jta.platform.spi.JtaPlatform");
+		}
+		catch (ClassNotFoundException ex) {
+			try {
+				// Try Hibernate 4.3 JtaPlatform variant
+				jpClass = SpringSessionContext.class.getClassLoader().loadClass(
+						"org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform");
+			}
+			catch (ClassNotFoundException ex2) {
+				throw new IllegalStateException("Neither Hibernate 4.0-4.2 nor 4.3 variant of JtaPlatform found");
+			}
+		}
+		jtaPlatformClass = (Class<? extends Service>) jpClass;
+	}
+
+	static String getJtaPlatformBasePackage() {
+		String className = jtaPlatformClass.getName();
+		return className.substring(0, className.length() - "spi.JtaPlatform".length());
+	}
 
 	private final TransactionManager transactionManager;
 
 	private final UserTransaction userTransaction;
 
+	private final TransactionSynchronizationRegistry transactionSynchronizationRegistry;
 
 	/**
 	 * Create a new ConfigurableJtaPlatform instance with the given
 	 * JTA TransactionManager and optionally a given UserTransaction.
 	 * @param tm the JTA TransactionManager reference (required)
 	 * @param ut the JTA UserTransaction reference (optional)
+	 * @param tsr the JTA 1.1 TransactionSynchronizationRegistry (optional)
 	 */
-	public ConfigurableJtaPlatform(TransactionManager tm, UserTransaction ut) {
+	public ConfigurableJtaPlatform(TransactionManager tm, UserTransaction ut, TransactionSynchronizationRegistry tsr) {
 		Assert.notNull(tm, "TransactionManager reference must not be null");
 		this.transactionManager = tm;
 		this.userTransaction = (ut != null ? ut : new UserTransactionAdapter(tm));
+		this.transactionSynchronizationRegistry = tsr;
 	}
 
 
-	@Override
-	protected TransactionManager locateTransactionManager() {
+	public TransactionManager retrieveTransactionManager() {
 		return this.transactionManager;
 	}
 
-	@Override
-	protected UserTransaction locateUserTransaction() {
+	public UserTransaction retrieveUserTransaction() {
 		return this.userTransaction;
 	}
 
-	@Override
-	protected boolean canCacheTransactionManager() {
-		return true;
+	public Object getTransactionIdentifier(Transaction transaction) {
+		return transaction;
+ 	}
+ 
+	public boolean canRegisterSynchronization() {
+		try {
+			return (this.transactionManager.getStatus() == Status.STATUS_ACTIVE);
+		}
+		catch (SystemException ex) {
+			throw new TransactionException("Could not determine JTA transaction status", ex);
+		}
+	}
+
+	public void registerSynchronization(Synchronization synchronization) {
+		if (this.transactionSynchronizationRegistry != null) {
+			this.transactionSynchronizationRegistry.registerInterposedSynchronization(synchronization);
+		}
+		else {
+			try {
+				this.transactionManager.getTransaction().registerSynchronization(synchronization);
+			}
+			catch (Exception ex) {
+				throw new TransactionException("Could not access JTA Transaction to register synchronization", ex);
+			}
+		}
+	}
+
+	public int getCurrentStatus() throws SystemException {
+		return this.transactionManager.getStatus();
 	}
 
-	@Override
-	protected boolean canCacheUserTransaction() {
-		return true;
+	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+		Method targetMethod = getClass().getMethod(method.getName(), method.getParameterTypes());
+		return targetMethod.invoke(this, args);
 	}
 
+	/**
+	 * Obtain a proxy that implements the current Hibernate version's JtaPlatform interface
+	 * in the right package location, delegating all invocations to the same-named methods
+	 * on this ConfigurableJtaPlatform class itself.
+	 */
+	public Object getJtaPlatformProxy() {
+		return Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] {jtaPlatformClass}, this);
+ 	}
+
 }
diff -Nru spring-framework-3.2.18.RELEASE/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/LocalSessionFactoryBuilder.java spring-framework-3.2.18.RELEASE.hibernate4.3/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/LocalSessionFactoryBuilder.java
--- spring-framework-3.2.18.RELEASE/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/LocalSessionFactoryBuilder.java	2016-12-21 19:42:08.000000000 +0100
+++ spring-framework-3.2.18.RELEASE.hibernate4.3/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/LocalSessionFactoryBuilder.java	2016-12-22 20:38:31.548142550 +0100
@@ -30,7 +30,6 @@
 import org.hibernate.cfg.Configuration;
 import org.hibernate.cfg.Environment;
 import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
-import org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform;
 
 import org.springframework.core.io.Resource;
 import org.springframework.core.io.ResourceLoader;
@@ -127,7 +126,7 @@
 	 * instructing Hibernate to interact with externally managed transactions.
 	 * <p>A passed-in Spring {@link JtaTransactionManager} needs to contain a JTA
 	 * {@link TransactionManager} reference to be usable here, except for the WebSphere
-	 * case where we'll automatically set {@link WebSphereExtendedJtaPlatform} accordingly.
+	 * case where we'll automatically set {@code WebSphereExtendedJtaPlatform} accordingly.
 	 * <p>Note: If this is set, the Hibernate settings should not contain a JTA platform
 	 * setting to avoid meaningless double configuration.
 	 */
@@ -136,7 +135,8 @@
 		if (jtaTransactionManager instanceof JtaTransactionManager) {
 			boolean webspherePresent = ClassUtils.isPresent("com.ibm.wsspi.uow.UOWManager", getClass().getClassLoader());
 			if (webspherePresent) {
-				getProperties().put(AvailableSettings.JTA_PLATFORM, new WebSphereExtendedJtaPlatform());
+				getProperties().put(AvailableSettings.JTA_PLATFORM,
+						ConfigurableJtaPlatform.getJtaPlatformBasePackage() + "internal.WebSphereExtendedJtaPlatform");
 			}
 			else {
 				JtaTransactionManager jtaTm = (JtaTransactionManager) jtaTransactionManager;
@@ -145,12 +145,13 @@
 							"Can only apply JtaTransactionManager which has a TransactionManager reference set");
 				}
 				getProperties().put(AvailableSettings.JTA_PLATFORM,
-						new ConfigurableJtaPlatform(jtaTm.getTransactionManager(), jtaTm.getUserTransaction()));
+						new ConfigurableJtaPlatform(jtaTm.getTransactionManager(), jtaTm.getUserTransaction(),
+								jtaTm.getTransactionSynchronizationRegistry()).getJtaPlatformProxy());
 			}
 		}
 		else if (jtaTransactionManager instanceof TransactionManager) {
 			getProperties().put(AvailableSettings.JTA_PLATFORM,
-					new ConfigurableJtaPlatform((TransactionManager) jtaTransactionManager, null));
+					new ConfigurableJtaPlatform((TransactionManager) jtaTransactionManager, null, null).getJtaPlatformProxy());
 		}
 		else {
 			throw new IllegalArgumentException(
diff -Nru spring-framework-3.2.18.RELEASE/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/SessionFactoryUtils.java spring-framework-3.2.18.RELEASE.hibernate4.3/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/SessionFactoryUtils.java
--- spring-framework-3.2.18.RELEASE/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/SessionFactoryUtils.java	2016-12-21 19:42:08.000000000 +0100
+++ spring-framework-3.2.18.RELEASE.hibernate4.3/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/SessionFactoryUtils.java	2016-12-23 10:44:05.095253068 +0100
@@ -16,6 +16,7 @@
 
 package org.springframework.orm.hibernate4;
 
+import java.lang.reflect.Method;
 import javax.sql.DataSource;
 
 import org.apache.commons.logging.Log;
@@ -41,7 +42,7 @@
 import org.hibernate.exception.JDBCConnectionException;
 import org.hibernate.exception.LockAcquisitionException;
 import org.hibernate.exception.SQLGrammarException;
-import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
+import org.hibernate.service.spi.Wrapped;
 
 import org.springframework.dao.CannotAcquireLockException;
 import org.springframework.dao.DataAccessException;
@@ -52,6 +53,8 @@
 import org.springframework.dao.InvalidDataAccessApiUsageException;
 import org.springframework.dao.InvalidDataAccessResourceUsageException;
 import org.springframework.jdbc.datasource.DataSourceUtils;
+import org.springframework.util.ClassUtils;
+import org.springframework.util.ReflectionUtils;
 
 /**
  * Helper class featuring methods for Hibernate Session handling.
@@ -78,6 +81,11 @@
 
 	static final Log logger = LogFactory.getLog(SessionFactoryUtils.class);
 
+	/**
+	 * Bridging between the different ConnectionProvider package location in 4.0-4.2 vs 4.3.
+	 */
+	private static final Method getConnectionProviderMethod =
+			ClassUtils.getMethodIfAvailable(SessionFactoryImplementor.class, "getConnectionProvider");
 
 	/**
 	 * Determine the DataSource of the given SessionFactory.
@@ -86,8 +94,8 @@
 	 * @see org.hibernate.engine.spi.SessionFactoryImplementor#getConnectionProvider
 	 */
 	public static DataSource getDataSource(SessionFactory sessionFactory) {
-		if (sessionFactory instanceof SessionFactoryImplementor) {
-			ConnectionProvider cp = ((SessionFactoryImplementor) sessionFactory).getConnectionProvider();
+		if (getConnectionProviderMethod != null && sessionFactory instanceof SessionFactoryImplementor) {
+			Wrapped cp = (Wrapped) ReflectionUtils.invokeMethod(getConnectionProviderMethod, sessionFactory);
 			return cp.unwrap(DataSource.class);
 		}
 		return null;
diff -Nru spring-framework-3.2.18.RELEASE/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/SpringSessionContext.java spring-framework-3.2.18.RELEASE.hibernate4.3/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/SpringSessionContext.java
--- spring-framework-3.2.18.RELEASE/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/SpringSessionContext.java	2016-12-21 19:42:08.000000000 +0100
+++ spring-framework-3.2.18.RELEASE.hibernate4.3/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/SpringSessionContext.java	2016-12-22 20:45:06.119514785 +0100
@@ -16,16 +16,16 @@
 
 package org.springframework.orm.hibernate4;
 
-import javax.transaction.TransactionManager;
+import java.lang.reflect.Method;
 
 import org.hibernate.FlushMode;
 import org.hibernate.HibernateException;
 import org.hibernate.Session;
 import org.hibernate.context.spi.CurrentSessionContext;
 import org.hibernate.engine.spi.SessionFactoryImplementor;
-import org.hibernate.service.jta.platform.spi.JtaPlatform;
 
 import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.util.ReflectionUtils;
 
 /**
  * Implementation of Hibernate 3.1's CurrentSessionContext interface
@@ -44,7 +44,7 @@
 
 	private final SessionFactoryImplementor sessionFactory;
 
-	private final CurrentSessionContext jtaSessionContext;
+	private CurrentSessionContext jtaSessionContext;
 
 
 	/**
@@ -53,15 +53,24 @@
 	 */
 	public SpringSessionContext(SessionFactoryImplementor sessionFactory) {
 		this.sessionFactory = sessionFactory;
-		JtaPlatform jtaPlatform = sessionFactory.getServiceRegistry().getService(JtaPlatform.class);
-		TransactionManager transactionManager = jtaPlatform.retrieveTransactionManager();
-		this.jtaSessionContext = (transactionManager != null ? new SpringJtaSessionContext(sessionFactory) : null);
+		try {
+			Object jtaPlatform = sessionFactory.getServiceRegistry().getService(ConfigurableJtaPlatform.jtaPlatformClass);
+			Method rtmMethod = ConfigurableJtaPlatform.jtaPlatformClass.getMethod("retrieveTransactionManager");
+			Object transactionManager = ReflectionUtils.invokeMethod(rtmMethod, jtaPlatform);
+			if (transactionManager != null) {
+				this.jtaSessionContext = new SpringJtaSessionContext(sessionFactory);
+			}
+		}
+		catch (Exception ex) {
+			throw new IllegalStateException("Could not introspect Hibernate JtaPlatform for SpringJtaSessionContext", ex);
+		}
 	}
 
 
 	/**
 	 * Retrieve the Spring-managed Session for the current thread, if any.
 	 */
+	@Override
 	public Session currentSession() throws HibernateException {
 		Object value = TransactionSynchronizationManager.getResource(this.sessionFactory);
 		if (value instanceof Session) {
@@ -70,15 +79,15 @@
 		else if (value instanceof SessionHolder) {
 			SessionHolder sessionHolder = (SessionHolder) value;
 			Session session = sessionHolder.getSession();
-			if (!sessionHolder.isSynchronizedWithTransaction() &&
-					TransactionSynchronizationManager.isSynchronizationActive()) {
+			if (TransactionSynchronizationManager.isSynchronizationActive() &&
+					!sessionHolder.isSynchronizedWithTransaction()) {
 				TransactionSynchronizationManager.registerSynchronization(
 						new SpringSessionSynchronization(sessionHolder, this.sessionFactory));
 				sessionHolder.setSynchronizedWithTransaction(true);
 				// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
 				// with FlushMode.MANUAL, which needs to allow flushing within the transaction.
 				FlushMode flushMode = session.getFlushMode();
-				if (FlushMode.isManualFlushMode(flushMode) &&
+				if (flushMode.equals(FlushMode.MANUAL) &&
 						!TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
 					session.setFlushMode(FlushMode.AUTO);
 					sessionHolder.setPreviousFlushMode(flushMode);
diff -Nru spring-framework-3.2.18.RELEASE/spring-tx/src/main/java/org/springframework/transaction/jta/JtaTransactionManager.java spring-framework-3.2.18.RELEASE.hibernate4.3/spring-tx/src/main/java/org/springframework/transaction/jta/JtaTransactionManager.java
--- spring-framework-3.2.18.RELEASE/spring-tx/src/main/java/org/springframework/transaction/jta/JtaTransactionManager.java	2016-12-21 19:42:08.000000000 +0100
+++ spring-framework-3.2.18.RELEASE.hibernate4.3/spring-tx/src/main/java/org/springframework/transaction/jta/JtaTransactionManager.java	2016-12-22 21:08:45.109820257 +0100
@@ -28,7 +28,6 @@
 import javax.transaction.NotSupportedException;
 import javax.transaction.RollbackException;
 import javax.transaction.Status;
-import javax.transaction.Synchronization;
 import javax.transaction.SystemException;
 import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
@@ -50,7 +49,6 @@
 import org.springframework.transaction.support.DefaultTransactionStatus;
 import org.springframework.transaction.support.TransactionSynchronization;
 import org.springframework.util.Assert;
-import org.springframework.util.ClassUtils;
 import org.springframework.util.StringUtils;
 
 /**
@@ -101,8 +99,8 @@
  * JtaTransactionManager autodetects the TransactionSynchronizationRegistry and uses
  * it for registering Spring-managed synchronizations when participating in an existing
  * JTA transaction (e.g. controlled by EJB CMT). If no TransactionSynchronizationRegistry
- * is available (or the JTA 1.1 API isn't available), then such synchronizations will be
- * registered via the (non-EE) JTA TransactionManager handle.
+ * is available, then such synchronizations will be registered via the (non-EE) JTA
+ * TransactionManager handle.
  *
  * <p>This class is serializable. However, active synchronizations do not survive serialization.
  *
@@ -148,22 +146,6 @@
 			"java:comp/TransactionSynchronizationRegistry";
 
 
-	private static final String TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME =
-			"javax.transaction.TransactionSynchronizationRegistry";
-
-	private static Class<?> transactionSynchronizationRegistryClass;
-
-	static {
-		try {
-			transactionSynchronizationRegistryClass = ClassUtils.forName(
-					TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME, JtaTransactionManager.class.getClassLoader());
-		}
-		catch (ClassNotFoundException ex) {
-			// JTA 1.1 API not available... simply proceed the JTA 1.0 way.
-		}
-	}
-
-
 	private transient JndiTemplate jndiTemplate = new JndiTemplate();
 
 	private transient UserTransaction userTransaction;
@@ -182,9 +164,11 @@
 
 	private boolean autodetectTransactionManager = true;
 
+	private transient TransactionSynchronizationRegistry transactionSynchronizationRegistry;
+
 	private String transactionSynchronizationRegistryName;
 
-	private transient Object transactionSynchronizationRegistry;
+	private boolean autodetectTransactionSynchronizationRegistry = true;
 
 	private boolean allowCustomIsolationLevels = false;
 
@@ -352,6 +336,28 @@
 	}
 
 	/**
+	 * Set the JTA 1.1 TransactionSynchronizationRegistry to use as direct reference.
+	 * <p>A TransactionSynchronizationRegistry allows for interposed registration
+	 * of transaction synchronizations, as an alternative to the regular registration
+	 * methods on the JTA TransactionManager API. Also, it is an official part of the
+	 * Java EE 5 platform, in contrast to the JTA TransactionManager itself.
+	 * <p>Note that the TransactionSynchronizationRegistry will be autodetected in JNDI and
+	 * also from the UserTransaction/TransactionManager object if implemented there as well.
+	 * @see #setTransactionSynchronizationRegistryName
+	 * @see #setAutodetectTransactionSynchronizationRegistry
+	 */
+	public void setTransactionSynchronizationRegistry(TransactionSynchronizationRegistry transactionSynchronizationRegistry) {
+		this.transactionSynchronizationRegistry = transactionSynchronizationRegistry;
+	}
+
+	/**
+	 * Return the JTA 1.1 TransactionSynchronizationRegistry that this transaction manager uses, if any.
+	 */
+	public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() {
+		return this.transactionSynchronizationRegistry;
+	}
+
+	/**
 	 * Set the JNDI name of the JTA TransactionManager.
 	 * <p>A TransactionManager is necessary for suspending and resuming transactions,
 	 * as this not supported by the UserTransaction interface.
@@ -393,6 +399,20 @@
 	}
 
 	/**
+	 * Set whether to autodetect a JTA 1.1 TransactionSynchronizationRegistry object
+	 * at its default JDNI location ("java:comp/TransactionSynchronizationRegistry")
+	 * if the UserTransaction has also been obtained from JNDI, and also whether
+	 * to fall back to checking whether the JTA UserTransaction/TransactionManager
+	 * object implements the JTA TransactionSynchronizationRegistry interface too.
+	 * <p>Default is "true", autodetecting the TransactionSynchronizationRegistry
+	 * unless it has been specified explicitly. Can be turned off to delegate
+	 * synchronization registration to the regular JTA TransactionManager API.
+	 */
+	public void setAutodetectTransactionSynchronizationRegistry(boolean autodetectTransactionSynchronizationRegistry) {
+		this.autodetectTransactionSynchronizationRegistry = autodetectTransactionSynchronizationRegistry;
+	}
+
+	/**
 	 * Set whether to allow custom isolation levels to be specified.
 	 * <p>Default is "false", throwing an exception if a non-default isolation level
 	 * is specified for a transaction. Turn this flag on if affected resource adapters
@@ -410,6 +430,7 @@
 	 * Initialize the UserTransaction as well as the TransactionManager handle.
 	 * @see #initUserTransactionAndTransactionManager()
 	 */
+	@Override
 	public void afterPropertiesSet() throws TransactionSystemException {
 		initUserTransactionAndTransactionManager();
 		checkUserTransactionAndTransactionManager();
@@ -421,38 +442,36 @@
 	 * @throws TransactionSystemException if initialization failed
 	 */
 	protected void initUserTransactionAndTransactionManager() throws TransactionSystemException {
-		// Fetch JTA UserTransaction from JNDI, if necessary.
 		if (this.userTransaction == null) {
+			// Fetch JTA UserTransaction from JNDI, if necessary.
 			if (StringUtils.hasLength(this.userTransactionName)) {
 				this.userTransaction = lookupUserTransaction(this.userTransactionName);
 				this.userTransactionObtainedFromJndi = true;
 			}
 			else {
 				this.userTransaction = retrieveUserTransaction();
+				if (this.userTransaction == null && this.autodetectUserTransaction) {
+					// Autodetect UserTransaction at its default JNDI location.
+					this.userTransaction = findUserTransaction();
+				}
 			}
 		}
 
-		// Fetch JTA TransactionManager from JNDI, if necessary.
 		if (this.transactionManager == null) {
+			// Fetch JTA TransactionManager from JNDI, if necessary.
 			if (StringUtils.hasLength(this.transactionManagerName)) {
 				this.transactionManager = lookupTransactionManager(this.transactionManagerName);
 			}
 			else {
 				this.transactionManager = retrieveTransactionManager();
+				if (this.transactionManager == null && this.autodetectTransactionManager) {
+					// Autodetect UserTransaction object that implements TransactionManager,
+					// and check fallback JNDI locations otherwise.
+					this.transactionManager = findTransactionManager(this.userTransaction);
+				}
 			}
 		}
 
-		// Autodetect UserTransaction at its default JNDI location.
-		if (this.userTransaction == null && this.autodetectUserTransaction) {
-			this.userTransaction = findUserTransaction();
-		}
-
-		// Autodetect UserTransaction object that implements TransactionManager,
-		// and check fallback JNDI locations otherwise.
-		if (this.transactionManager == null && this.autodetectTransactionManager) {
-			this.transactionManager = findTransactionManager(this.userTransaction);
-		}
-
 		// If only JTA TransactionManager specified, create UserTransaction handle for it.
 		if (this.userTransaction == null && this.transactionManager != null) {
 			this.userTransaction = buildUserTransaction(this.transactionManager);
@@ -494,15 +513,20 @@
 	 * @throws TransactionSystemException if initialization failed
 	 */
 	protected void initTransactionSynchronizationRegistry() {
-		if (StringUtils.hasLength(this.transactionSynchronizationRegistryName)) {
-			this.transactionSynchronizationRegistry =
-					lookupTransactionSynchronizationRegistry(this.transactionSynchronizationRegistryName);
-		}
-		else {
-			this.transactionSynchronizationRegistry = retrieveTransactionSynchronizationRegistry();
-			if (this.transactionSynchronizationRegistry == null) {
+		if (this.transactionSynchronizationRegistry == null) {
+			// Fetch JTA TransactionSynchronizationRegistry from JNDI, if necessary.
+			if (StringUtils.hasLength(this.transactionSynchronizationRegistryName)) {
 				this.transactionSynchronizationRegistry =
-						findTransactionSynchronizationRegistry(this.userTransaction, this.transactionManager);
+						lookupTransactionSynchronizationRegistry(this.transactionSynchronizationRegistryName);
+			}
+			else {
+				this.transactionSynchronizationRegistry = retrieveTransactionSynchronizationRegistry();
+				if (this.transactionSynchronizationRegistry == null && this.autodetectTransactionSynchronizationRegistry) {
+					// Autodetect in JNDI if applicable, and check UserTransaction/TransactionManager
+					// object that implements TransactionSynchronizationRegistry otherwise.
+					this.transactionSynchronizationRegistry =
+							findTransactionSynchronizationRegistry(this.userTransaction, this.transactionManager);
+				}
 			}
 		}
 
@@ -586,16 +610,12 @@
 	 * @see #setJndiTemplate
 	 * @see #setTransactionSynchronizationRegistryName
 	 */
-	protected Object lookupTransactionSynchronizationRegistry(String registryName) throws TransactionSystemException {
-		if (transactionSynchronizationRegistryClass == null) {
-			throw new TransactionSystemException(
-					"JTA 1.1 [" + TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME + "] API not available");
-		}
+	protected TransactionSynchronizationRegistry lookupTransactionSynchronizationRegistry(String registryName) throws TransactionSystemException {
 		try {
 			if (logger.isDebugEnabled()) {
 				logger.debug("Retrieving JTA TransactionSynchronizationRegistry from JNDI location [" + registryName + "]");
 			}
-			return getJndiTemplate().lookup(registryName, transactionSynchronizationRegistryClass);
+			return getJndiTemplate().lookup(registryName, TransactionSynchronizationRegistry.class);
 		}
 		catch (NamingException ex) {
 			throw new TransactionSystemException(
@@ -637,7 +657,7 @@
 	 * or {@code null} if none found
 	 * @throws TransactionSystemException in case of errors
 	 */
-	protected Object retrieveTransactionSynchronizationRegistry() throws TransactionSystemException {
+	protected TransactionSynchronizationRegistry retrieveTransactionSynchronizationRegistry() throws TransactionSystemException {
 		return null;
 	}
 
@@ -712,24 +732,15 @@
 	 * or {@code null} if none found
 	 * @throws TransactionSystemException in case of errors
 	 */
-	protected Object findTransactionSynchronizationRegistry(UserTransaction ut, TransactionManager tm)
+	protected TransactionSynchronizationRegistry findTransactionSynchronizationRegistry(UserTransaction ut, TransactionManager tm)
 			throws TransactionSystemException {
 
-		if (transactionSynchronizationRegistryClass == null) {
-			// JTA 1.1 API not present - skip.
-			if (logger.isDebugEnabled()) {
-				logger.debug("JTA 1.1 [" + TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME + "] API not available");
-			}
-			return null;
-		}
-
-		// If we came here, we might be on Java EE 5, since the JTA 1.1 API is present.
 		if (this.userTransactionObtainedFromJndi) {
 			// UserTransaction has already been obtained from JNDI, so the
 			// TransactionSynchronizationRegistry probably sits there as well.
 			String jndiName = DEFAULT_TRANSACTION_SYNCHRONIZATION_REGISTRY_NAME;
 			try {
-				Object tsr = getJndiTemplate().lookup(jndiName, transactionSynchronizationRegistryClass);
+				TransactionSynchronizationRegistry tsr = getJndiTemplate().lookup(jndiName, TransactionSynchronizationRegistry.class);
 				if (logger.isDebugEnabled()) {
 					logger.debug("JTA TransactionSynchronizationRegistry found at default JNDI location [" + jndiName + "]");
 				}
@@ -742,14 +753,13 @@
 			}
 		}
 		// Check whether the UserTransaction or TransactionManager implements it...
-		if (transactionSynchronizationRegistryClass.isInstance(ut)) {
-			return ut;
+		if (ut instanceof TransactionSynchronizationRegistry) {
+			return (TransactionSynchronizationRegistry) ut;
 		}
-		if (transactionSynchronizationRegistryClass.isInstance(tm)) {
-			return tm;
+		if (tm instanceof TransactionSynchronizationRegistry) {
+			return (TransactionSynchronizationRegistry) tm;
 		}
-		// OK, so no JTA 1.1 TransactionSynchronizationRegistry is available,
-		// despite the API being present...
+		// OK, so no JTA 1.1 TransactionSynchronizationRegistry is available...
 		return null;
 	}
 
@@ -1136,7 +1146,7 @@
 
 		if (this.transactionSynchronizationRegistry != null) {
 			// JTA 1.1 TransactionSynchronizationRegistry available - use it.
-			new InterposedSynchronizationDelegate().registerInterposedSynchronization(
+			this.transactionSynchronizationRegistry.registerInterposedSynchronization(
 					new JtaAfterCompletionSynchronization(synchronizations));
 		}
 
@@ -1163,6 +1173,7 @@
 	// Implementation of TransactionFactory interface
 	//---------------------------------------------------------------------
 
+	@Override
 	public Transaction createTransaction(String name, int timeout) throws NotSupportedException, SystemException {
 		TransactionManager tm = getTransactionManager();
 		Assert.state(tm != null, "No JTA TransactionManager available");
@@ -1173,6 +1184,7 @@
 		return new ManagedTransactionAdapter(tm);
 	}
 
+	@Override
 	public boolean supportsResourceAdapterManagedTransactions() {
 		return false;
 	}
@@ -1194,16 +1206,4 @@
 		initTransactionSynchronizationRegistry();
 	}
 
-
-	/**
-	 * Inner class to avoid a direct dependency on the JTA 1.1 API
-	 * (javax.transaction.TransactionSynchronizationRegistry interface).
-	 */
-	private class InterposedSynchronizationDelegate {
-
-		public void registerInterposedSynchronization(Synchronization synch) {
-			((TransactionSynchronizationRegistry) transactionSynchronizationRegistry).registerInterposedSynchronization(synch);
-		}
-	}
-
 }
