diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.java b/spring-orm/src/main/java/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.java index 127924c7bd..a325d602a2 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.java @@ -166,7 +166,6 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter { return this.flushMode; } - /** * The default value is "true" so that the filter may re-bind the opened * {@code Session} to each asynchronously dispatched thread and postpone @@ -186,6 +185,7 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter { boolean participate = false; WebAsyncManager asyncManager = AsyncWebUtils.getAsyncManager(request); + boolean isFirstRequest = !isAsyncDispatch(request); String key = getAlreadyFilteredAttributeName(); if (isSingleSession()) { @@ -195,7 +195,7 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter { participate = true; } else { - if (!isAsyncDispatch(request) || !asyncManager.initializeAsyncThread(key)) { + if (isFirstRequest || !asyncManager.initializeAsyncThread(key)) { logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter"); Session session = getSession(sessionFactory); SessionHolder sessionHolder = new SessionHolder(session); @@ -240,19 +240,6 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter { } } - private WebAsyncThreadInitializer createAsyncThreadInitializer(final SessionFactory sessionFactory, - final SessionHolder sessionHolder) { - - return new WebAsyncThreadInitializer() { - public void initialize() { - TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder); - } - public void reset() { - TransactionSynchronizationManager.unbindResource(sessionFactory); - } - }; - } - /** * Look up the SessionFactory that this filter should use, * taking the current HTTP request as argument. @@ -317,4 +304,17 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter { SessionFactoryUtils.closeSession(session); } + private WebAsyncThreadInitializer createAsyncThreadInitializer(final SessionFactory sessionFactory, + final SessionHolder sessionHolder) { + + return new WebAsyncThreadInitializer() { + public void initialize() { + TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder); + } + public void reset() { + TransactionSynchronizationManager.unbindResource(sessionFactory); + } + }; + } + } diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate4/support/OpenSessionInViewFilter.java b/spring-orm/src/main/java/org/springframework/orm/hibernate4/support/OpenSessionInViewFilter.java index 929af55bd4..d5d21f05a5 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate4/support/OpenSessionInViewFilter.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate4/support/OpenSessionInViewFilter.java @@ -99,7 +99,6 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter { return this.sessionFactoryBeanName; } - /** * The default value is "true" so that the filter may re-bind the opened * {@code Session} to each asynchronously dispatched thread and postpone @@ -119,6 +118,7 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter { boolean participate = false; WebAsyncManager asyncManager = AsyncWebUtils.getAsyncManager(request); + boolean isFirstRequest = !isAsyncDispatch(request); String key = getAlreadyFilteredAttributeName(); if (TransactionSynchronizationManager.hasResource(sessionFactory)) { @@ -126,7 +126,7 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter { participate = true; } else { - if (!isAsyncDispatch(request) || !asyncManager.initializeAsyncThread(key)) { + if (isFirstRequest || !asyncManager.initializeAsyncThread(key)) { logger.debug("Opening Hibernate Session in OpenSessionInViewFilter"); Session session = openSession(sessionFactory); SessionHolder sessionHolder = new SessionHolder(session); @@ -153,19 +153,6 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter { } } - private WebAsyncThreadInitializer createAsyncThreadInitializer(final SessionFactory sessionFactory, - final SessionHolder sessionHolder) { - - return new WebAsyncThreadInitializer() { - public void initialize() { - TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder); - } - public void reset() { - TransactionSynchronizationManager.unbindResource(sessionFactory); - } - }; - } - /** * Look up the SessionFactory that this filter should use, * taking the current HTTP request as argument. @@ -214,4 +201,17 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter { } } + private WebAsyncThreadInitializer createAsyncThreadInitializer(final SessionFactory sessionFactory, + final SessionHolder sessionHolder) { + + return new WebAsyncThreadInitializer() { + public void initialize() { + TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder); + } + public void reset() { + TransactionSynchronizationManager.unbindResource(sessionFactory); + } + }; + } + } diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate4/support/OpenSessionInViewInterceptor.java b/spring-orm/src/main/java/org/springframework/orm/hibernate4/support/OpenSessionInViewInterceptor.java index 2a2678bd6f..84cd22f001 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate4/support/OpenSessionInViewInterceptor.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate4/support/OpenSessionInViewInterceptor.java @@ -105,9 +105,9 @@ public class OpenSessionInViewInterceptor implements AsyncWebRequestInterceptor */ public void preHandle(WebRequest request) throws DataAccessException { - WebAsyncManager asyncManager = AsyncWebUtils.getAsyncManager(request); String participateAttributeName = getParticipateAttributeName(); + WebAsyncManager asyncManager = AsyncWebUtils.getAsyncManager(request); if (asyncManager.hasConcurrentResult()) { if (asyncManager.initializeAsyncThread(participateAttributeName)) { return; @@ -148,12 +148,6 @@ public class OpenSessionInViewInterceptor implements AsyncWebRequestInterceptor } } - public void afterConcurrentHandlingStarted(WebRequest request) { - if (!decrementParticipateCount(request)) { - TransactionSynchronizationManager.unbindResource(getSessionFactory()); - } - } - private boolean decrementParticipateCount(WebRequest request) { String participateAttributeName = getParticipateAttributeName(); Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST); @@ -170,6 +164,12 @@ public class OpenSessionInViewInterceptor implements AsyncWebRequestInterceptor return true; } + public void afterConcurrentHandlingStarted(WebRequest request) { + if (!decrementParticipateCount(request)) { + TransactionSynchronizationManager.unbindResource(getSessionFactory()); + } + } + /** * Open a Session for the SessionFactory that this interceptor uses. *
The default implementation delegates to the
diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.java b/spring-orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.java
index 895ef6573d..d2117f5ab4 100644
--- a/spring-orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.java
+++ b/spring-orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.java
@@ -17,6 +17,7 @@
package org.springframework.orm.jpa.support;
import java.io.IOException;
+
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceException;
@@ -31,6 +32,9 @@ import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.StringUtils;
import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.request.async.AsyncWebUtils;
+import org.springframework.web.context.request.async.WebAsyncManager;
+import org.springframework.web.context.request.async.WebAsyncManager.WebAsyncThreadInitializer;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.filter.OncePerRequestFilter;
@@ -119,6 +123,15 @@ public class OpenEntityManagerInViewFilter extends OncePerRequestFilter {
return this.persistenceUnitName;
}
+ /**
+ * The default value is "true" so that the filter may re-bind the opened
+ * {@code EntityManager} to each asynchronously dispatched thread and postpone
+ * closing it until the very last asynchronous dispatch.
+ */
+ @Override
+ protected boolean shouldFilterAsyncDispatches() {
+ return true;
+ }
@Override
protected void doFilterInternal(
@@ -128,18 +141,28 @@ public class OpenEntityManagerInViewFilter extends OncePerRequestFilter {
EntityManagerFactory emf = lookupEntityManagerFactory(request);
boolean participate = false;
+ WebAsyncManager asyncManager = AsyncWebUtils.getAsyncManager(request);
+ boolean isFirstRequest = !isAsyncDispatch(request);
+ String key = getAlreadyFilteredAttributeName();
+
if (TransactionSynchronizationManager.hasResource(emf)) {
// Do not modify the EntityManager: just set the participate flag.
participate = true;
}
else {
- logger.debug("Opening JPA EntityManager in OpenEntityManagerInViewFilter");
- try {
- EntityManager em = createEntityManager(emf);
- TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em));
- }
- catch (PersistenceException ex) {
- throw new DataAccessResourceFailureException("Could not create JPA EntityManager", ex);
+ if (isFirstRequest || !asyncManager.initializeAsyncThread(key)) {
+ logger.debug("Opening JPA EntityManager in OpenEntityManagerInViewFilter");
+ try {
+ EntityManager em = createEntityManager(emf);
+ EntityManagerHolder emHolder = new EntityManagerHolder(em);
+ TransactionSynchronizationManager.bindResource(emf, emHolder);
+
+ WebAsyncThreadInitializer initializer = createAsyncThreadInitializer(emf, emHolder);
+ asyncManager.registerAsyncThreadInitializer(key, initializer);
+ }
+ catch (PersistenceException ex) {
+ throw new DataAccessResourceFailureException("Could not create JPA EntityManager", ex);
+ }
}
}
@@ -151,8 +174,10 @@ public class OpenEntityManagerInViewFilter extends OncePerRequestFilter {
if (!participate) {
EntityManagerHolder emHolder = (EntityManagerHolder)
TransactionSynchronizationManager.unbindResource(emf);
- logger.debug("Closing JPA EntityManager in OpenEntityManagerInViewFilter");
- EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());
+ if (isLastRequestThread(request)) {
+ logger.debug("Closing JPA EntityManager in OpenEntityManagerInViewFilter");
+ EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());
+ }
}
}
}
@@ -205,4 +230,17 @@ public class OpenEntityManagerInViewFilter extends OncePerRequestFilter {
return emf.createEntityManager();
}
+ private WebAsyncThreadInitializer createAsyncThreadInitializer(final EntityManagerFactory emFactory,
+ final EntityManagerHolder emHolder) {
+
+ return new WebAsyncThreadInitializer() {
+ public void initialize() {
+ TransactionSynchronizationManager.bindResource(emFactory, emHolder);
+ }
+ public void reset() {
+ TransactionSynchronizationManager.unbindResource(emFactory);
+ }
+ };
+ }
+
}
diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewInterceptor.java b/spring-orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewInterceptor.java
index d7abd61db2..7b30b81830 100644
--- a/spring-orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewInterceptor.java
+++ b/spring-orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewInterceptor.java
@@ -22,12 +22,15 @@ import javax.persistence.PersistenceException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.orm.jpa.EntityManagerFactoryAccessor;
-import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
+import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.WebRequest;
-import org.springframework.web.context.request.WebRequestInterceptor;
+import org.springframework.web.context.request.async.AsyncWebRequestInterceptor;
+import org.springframework.web.context.request.async.AsyncWebUtils;
+import org.springframework.web.context.request.async.WebAsyncManager;
+import org.springframework.web.context.request.async.WebAsyncManager.WebAsyncThreadInitializer;
/**
* Spring web request interceptor that binds a JPA EntityManager to the
@@ -56,7 +59,7 @@ import org.springframework.web.context.request.WebRequestInterceptor;
* @see org.springframework.orm.jpa.SharedEntityManagerCreator
* @see org.springframework.transaction.support.TransactionSynchronizationManager
*/
-public class OpenEntityManagerInViewInterceptor extends EntityManagerFactoryAccessor implements WebRequestInterceptor {
+public class OpenEntityManagerInViewInterceptor extends EntityManagerFactoryAccessor implements AsyncWebRequestInterceptor {
/**
* Suffix that gets appended to the EntityManagerFactory toString
@@ -68,9 +71,18 @@ public class OpenEntityManagerInViewInterceptor extends EntityManagerFactoryAcce
public void preHandle(WebRequest request) throws DataAccessException {
+
+ String participateAttributeName = getParticipateAttributeName();
+
+ WebAsyncManager asyncManager = AsyncWebUtils.getAsyncManager(request);
+ if (asyncManager.hasConcurrentResult()) {
+ if (asyncManager.initializeAsyncThread(participateAttributeName)) {
+ return;
+ }
+ }
+
if (TransactionSynchronizationManager.hasResource(getEntityManagerFactory())) {
// do not modify the EntityManager: just mark the request accordingly
- String participateAttributeName = getParticipateAttributeName();
Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
int newCount = (count != null ? count + 1 : 1);
request.setAttribute(getParticipateAttributeName(), newCount, WebRequest.SCOPE_REQUEST);
@@ -79,7 +91,11 @@ public class OpenEntityManagerInViewInterceptor extends EntityManagerFactoryAcce
logger.debug("Opening JPA EntityManager in OpenEntityManagerInViewInterceptor");
try {
EntityManager em = createEntityManager();
- TransactionSynchronizationManager.bindResource(getEntityManagerFactory(), new EntityManagerHolder(em));
+ EntityManagerHolder emHolder = new EntityManagerHolder(em);
+ TransactionSynchronizationManager.bindResource(getEntityManagerFactory(), emHolder);
+
+ WebAsyncThreadInitializer asyncThreadInitializer = createThreadInitializer(emHolder);
+ asyncManager.registerAsyncThreadInitializer(participateAttributeName, asyncThreadInitializer);
}
catch (PersistenceException ex) {
throw new DataAccessResourceFailureException("Could not create JPA EntityManager", ex);
@@ -91,18 +107,7 @@ public class OpenEntityManagerInViewInterceptor extends EntityManagerFactoryAcce
}
public void afterCompletion(WebRequest request, Exception ex) throws DataAccessException {
- String participateAttributeName = getParticipateAttributeName();
- Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
- if (count != null) {
- // Do not modify the EntityManager: just clear the marker.
- if (count > 1) {
- request.setAttribute(participateAttributeName, count - 1, WebRequest.SCOPE_REQUEST);
- }
- else {
- request.removeAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
- }
- }
- else {
+ if (!decrementParticipateCount(request)) {
EntityManagerHolder emHolder = (EntityManagerHolder)
TransactionSynchronizationManager.unbindResource(getEntityManagerFactory());
logger.debug("Closing JPA EntityManager in OpenEntityManagerInViewInterceptor");
@@ -110,6 +115,28 @@ public class OpenEntityManagerInViewInterceptor extends EntityManagerFactoryAcce
}
}
+ private boolean decrementParticipateCount(WebRequest request) {
+ String participateAttributeName = getParticipateAttributeName();
+ Integer count = (Integer) request.getAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
+ if (count == null) {
+ return false;
+ }
+ // Do not modify the Session: just clear the marker.
+ if (count > 1) {
+ request.setAttribute(participateAttributeName, count - 1, WebRequest.SCOPE_REQUEST);
+ }
+ else {
+ request.removeAttribute(participateAttributeName, WebRequest.SCOPE_REQUEST);
+ }
+ return true;
+ }
+
+ public void afterConcurrentHandlingStarted(WebRequest request) {
+ if (!decrementParticipateCount(request)) {
+ TransactionSynchronizationManager.unbindResource(getEntityManagerFactory());
+ }
+ }
+
/**
* Return the name of the request attribute that identifies that a request is
* already filtered. Default implementation takes the toString representation
@@ -120,4 +147,15 @@ public class OpenEntityManagerInViewInterceptor extends EntityManagerFactoryAcce
return getEntityManagerFactory().toString() + PARTICIPATE_SUFFIX;
}
+ private WebAsyncThreadInitializer createThreadInitializer(final EntityManagerHolder emHolder) {
+ return new WebAsyncThreadInitializer() {
+ public void initialize() {
+ TransactionSynchronizationManager.bindResource(getEntityManagerFactory(), emHolder);
+ }
+ public void reset() {
+ TransactionSynchronizationManager.unbindResource(getEntityManagerFactory());
+ }
+ };
+ }
+
}
diff --git a/spring-orm/src/test/java/org/springframework/orm/hibernate3/support/OpenSessionInViewTests.java b/spring-orm/src/test/java/org/springframework/orm/hibernate3/support/OpenSessionInViewTests.java
index 9a845214d5..087020ee3f 100644
--- a/spring-orm/src/test/java/org/springframework/orm/hibernate3/support/OpenSessionInViewTests.java
+++ b/spring-orm/src/test/java/org/springframework/orm/hibernate3/support/OpenSessionInViewTests.java
@@ -460,7 +460,7 @@ public class OpenSessionInViewTests {
final SessionFactory sf = createStrictMock(SessionFactory.class);
Session session = createStrictMock(Session.class);
- // Initial request during which concurrent handler execution starts..
+ // Initial request during which concurrent handling starts..
expect(sf.openSession()).andReturn(session);
expect(session.getSessionFactory()).andReturn(sf);
@@ -516,11 +516,10 @@ public class OpenSessionInViewTests {
reset(session);
reset(asyncWebRequest);
- // Async dispatch after concurrent handler execution results ready..
+ // Async dispatch after concurrent handling produces result ...
expect(session.close()).andReturn(null);
- expect(asyncWebRequest.isAsyncStarted()).andReturn(false);
- expectLastCall().anyTimes();
+ expect(asyncWebRequest.isAsyncStarted()).andReturn(false).anyTimes();
replay(sf);
replay(session);
diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewTests.java
index 1bae592894..dbccafd7f2 100644
--- a/spring-orm/src/test/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewTests.java
+++ b/spring-orm/src/test/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewTests.java
@@ -16,7 +16,21 @@
package org.springframework.orm.jpa.support;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
import java.io.IOException;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicInteger;
+
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.servlet.FilterChain;
@@ -25,7 +39,6 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import junit.framework.TestCase;
-import org.easymock.MockControl;
import org.springframework.mock.web.MockFilterConfig;
import org.springframework.mock.web.MockHttpServletRequest;
@@ -36,6 +49,9 @@ import org.springframework.orm.jpa.JpaTemplate;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.ServletWebRequest;
+import org.springframework.web.context.request.async.AsyncWebRequest;
+import org.springframework.web.context.request.async.AsyncWebUtils;
+import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.support.StaticWebApplicationContext;
/**
@@ -44,8 +60,6 @@ import org.springframework.web.context.support.StaticWebApplicationContext;
* @author Chris Beams
*/
public class OpenEntityManagerInViewTests extends TestCase {
-
- private MockControl factoryControl, managerControl;
private EntityManager manager;
@@ -56,15 +70,13 @@ public class OpenEntityManagerInViewTests extends TestCase {
@Override
protected void setUp() throws Exception {
- factoryControl = MockControl.createControl(EntityManagerFactory.class);
- factory = (EntityManagerFactory) factoryControl.getMock();
- managerControl = MockControl.createControl(EntityManager.class);
- manager = (EntityManager) managerControl.getMock();
+ factory = createMock(EntityManagerFactory.class);
+ manager = createMock(EntityManager.class);
template = new JpaTemplate(factory);
template.afterPropertiesSet();
- factoryControl.expectAndReturn(factory.createEntityManager(), manager);
+ expect(factory.createEntityManager()).andReturn(manager);
}
@Override
@@ -82,8 +94,7 @@ public class OpenEntityManagerInViewTests extends TestCase {
MockServletContext sc = new MockServletContext();
MockHttpServletRequest request = new MockHttpServletRequest(sc);
- managerControl.replay();
- factoryControl.replay();
+ replay(manager, factory);
interceptor.preHandle(new ServletWebRequest(request));
assertTrue(TransactionSynchronizationManager.hasResource(factory));
@@ -102,55 +113,131 @@ public class OpenEntityManagerInViewTests extends TestCase {
interceptor.postHandle(new ServletWebRequest(request), null);
interceptor.afterCompletion(new ServletWebRequest(request), null);
- factoryControl.verify();
- managerControl.verify();
+ verify(manager, factory);
- managerControl.reset();
- factoryControl.reset();
- managerControl.replay();
- factoryControl.replay();
+ reset(manager, factory);
+ replay(manager, factory);
interceptor.postHandle(new ServletWebRequest(request), null);
assertTrue(TransactionSynchronizationManager.hasResource(factory));
- factoryControl.verify();
- managerControl.verify();
+ verify(manager, factory);
- managerControl.reset();
- factoryControl.reset();
+ reset(manager, factory);
- managerControl.expectAndReturn(manager.isOpen(), true);
+ expect(manager.isOpen()).andReturn(true);
manager.close();
- managerControl.replay();
- factoryControl.replay();
+ replay(manager, factory);
interceptor.afterCompletion(new ServletWebRequest(request), null);
assertFalse(TransactionSynchronizationManager.hasResource(factory));
- factoryControl.verify();
- managerControl.verify();
+ verify(manager, factory);
+ }
+
+ public void testOpenEntityManagerInViewInterceptorAsyncScenario() throws Exception {
+
+ // Initial request thread
+
+ OpenEntityManagerInViewInterceptor interceptor = new OpenEntityManagerInViewInterceptor();
+ interceptor.setEntityManagerFactory(factory);
+
+ MockServletContext sc = new MockServletContext();
+ MockHttpServletRequest request = new MockHttpServletRequest(sc);
+ ServletWebRequest webRequest = new ServletWebRequest(request);
+
+ replay(manager, factory);
+
+ interceptor.preHandle(webRequest);
+ assertTrue(TransactionSynchronizationManager.hasResource(factory));
+
+ verify(manager, factory);
+
+ AsyncWebRequest asyncWebRequest = createStrictMock(AsyncWebRequest.class);
+ asyncWebRequest.addCompletionHandler((Runnable) anyObject());
+ asyncWebRequest.startAsync();
+ replay(asyncWebRequest);
+
+ WebAsyncManager asyncManager = AsyncWebUtils.getAsyncManager(webRequest);
+ asyncManager.setAsyncWebRequest(asyncWebRequest);
+
+ asyncManager.startCallableProcessing(new Callable