Skip to content

Commit f036ed6

Browse files
committed
Polish (major) MVC async processing interceptors
New afterTimeout and afterCompletion callbacks afterTimeout can provide a concurrent result to be used instead of the one that could not be set or returned on time Interceptor exceptions cause async processing to resume treating the exception as the concurrent result Adapter classes for convenient implementation of the interfaces Issue: SPR-9914
1 parent 06e34f0 commit f036ed6

File tree

23 files changed

+846
-319
lines changed

23 files changed

+846
-319
lines changed

spring-orm/src/main/java/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import org.springframework.util.Assert;
3535
import org.springframework.web.context.WebApplicationContext;
3636
import org.springframework.web.context.request.NativeWebRequest;
37-
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
37+
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
3838
import org.springframework.web.context.request.async.WebAsyncManager;
3939
import org.springframework.web.context.request.async.WebAsyncUtils;
4040
import org.springframework.web.context.support.WebApplicationContextUtils;
@@ -318,7 +318,7 @@ private boolean applySessionBindingInterceptor(WebAsyncManager asyncManager, Str
318318
/**
319319
* Bind and unbind the Hibernate {@code Session} to the current thread.
320320
*/
321-
private static class SessionBindingCallableInterceptor implements CallableProcessingInterceptor {
321+
private static class SessionBindingCallableInterceptor extends CallableProcessingInterceptorAdapter {
322322

323323
private final SessionFactory sessionFactory;
324324

@@ -329,16 +329,18 @@ public SessionBindingCallableInterceptor(SessionFactory sessionFactory, SessionH
329329
this.sessionHolder = sessionHolder;
330330
}
331331

332-
public void preProcess(NativeWebRequest request, Callable<?> task) {
332+
@Override
333+
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
333334
initializeThread();
334335
}
335336

336-
private void initializeThread() {
337-
TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder);
337+
@Override
338+
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
339+
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
338340
}
339341

340-
public void postProcess(NativeWebRequest request, Callable<?> task, Object concurrentResult) {
341-
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
342+
private void initializeThread() {
343+
TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder);
342344
}
343345
}
344346

spring-orm/src/main/java/org/springframework/orm/hibernate3/support/OpenSessionInViewInterceptor.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import org.springframework.web.context.request.AsyncWebRequestInterceptor;
3030
import org.springframework.web.context.request.NativeWebRequest;
3131
import org.springframework.web.context.request.WebRequest;
32-
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
32+
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
3333
import org.springframework.web.context.request.async.WebAsyncManager;
3434
import org.springframework.web.context.request.async.WebAsyncUtils;
3535

@@ -276,24 +276,26 @@ private boolean applySessionBindingInterceptor(WebAsyncManager asyncManager, Str
276276
/**
277277
* Bind and unbind the Hibernate {@code Session} to the current thread.
278278
*/
279-
private class SessionBindingCallableInterceptor implements CallableProcessingInterceptor {
279+
private class SessionBindingCallableInterceptor extends CallableProcessingInterceptorAdapter {
280280

281281
private final SessionHolder sessionHolder;
282282

283283
public SessionBindingCallableInterceptor(SessionHolder sessionHolder) {
284284
this.sessionHolder = sessionHolder;
285285
}
286286

287-
public void preProcess(NativeWebRequest request, Callable<?> task) {
287+
@Override
288+
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
288289
initializeThread();
289290
}
290291

291-
private void initializeThread() {
292-
TransactionSynchronizationManager.bindResource(getSessionFactory(), this.sessionHolder);
292+
@Override
293+
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
294+
TransactionSynchronizationManager.unbindResource(getSessionFactory());
293295
}
294296

295-
public void postProcess(NativeWebRequest request, Callable<?> task, Object concurrentResult) {
296-
TransactionSynchronizationManager.unbindResource(getSessionFactory());
297+
private void initializeThread() {
298+
TransactionSynchronizationManager.bindResource(getSessionFactory(), this.sessionHolder);
297299
}
298300
}
299301
}

spring-orm/src/main/java/org/springframework/orm/hibernate4/support/OpenSessionInViewFilter.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import org.springframework.transaction.support.TransactionSynchronizationManager;
3535
import org.springframework.web.context.WebApplicationContext;
3636
import org.springframework.web.context.request.NativeWebRequest;
37-
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
37+
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
3838
import org.springframework.web.context.request.async.WebAsyncManager;
3939
import org.springframework.web.context.request.async.WebAsyncUtils;
4040
import org.springframework.web.context.support.WebApplicationContextUtils;
@@ -215,7 +215,7 @@ private boolean applySessionBindingInterceptor(WebAsyncManager asyncManager, Str
215215
/**
216216
* Bind and unbind the Hibernate {@code Session} to the current thread.
217217
*/
218-
private static class SessionBindingCallableInterceptor implements CallableProcessingInterceptor {
218+
private static class SessionBindingCallableInterceptor extends CallableProcessingInterceptorAdapter {
219219

220220
private final SessionFactory sessionFactory;
221221

@@ -226,16 +226,18 @@ public SessionBindingCallableInterceptor(SessionFactory sessionFactory, SessionH
226226
this.sessionHolder = sessionHolder;
227227
}
228228

229-
public void preProcess(NativeWebRequest request, Callable<?> task) {
229+
@Override
230+
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
230231
initializeThread();
231232
}
232233

233-
private void initializeThread() {
234-
TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder);
234+
@Override
235+
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
236+
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
235237
}
236238

237-
public void postProcess(NativeWebRequest request, Callable<?> task, Object concurrentResult) {
238-
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
239+
private void initializeThread() {
240+
TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder);
239241
}
240242
}
241243
}

spring-orm/src/main/java/org/springframework/orm/hibernate4/support/OpenSessionInViewInterceptor.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import org.springframework.web.context.request.AsyncWebRequestInterceptor;
3434
import org.springframework.web.context.request.NativeWebRequest;
3535
import org.springframework.web.context.request.WebRequest;
36-
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
36+
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
3737
import org.springframework.web.context.request.async.WebAsyncManager;
3838
import org.springframework.web.context.request.async.WebAsyncUtils;
3939

@@ -215,24 +215,26 @@ private boolean applySessionBindingInterceptor(WebAsyncManager asyncManager, Str
215215
/**
216216
* Bind and unbind the Hibernate {@code Session} to the current thread.
217217
*/
218-
private class SessionBindingCallableInterceptor implements CallableProcessingInterceptor {
218+
private class SessionBindingCallableInterceptor extends CallableProcessingInterceptorAdapter {
219219

220220
private final SessionHolder sessionHolder;
221221

222222
public SessionBindingCallableInterceptor(SessionHolder sessionHolder) {
223223
this.sessionHolder = sessionHolder;
224224
}
225225

226-
public void preProcess(NativeWebRequest request, Callable<?> task) {
226+
@Override
227+
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
227228
initializeThread();
228229
}
229230

230-
private void initializeThread() {
231-
TransactionSynchronizationManager.bindResource(getSessionFactory(), this.sessionHolder);
231+
@Override
232+
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
233+
TransactionSynchronizationManager.unbindResource(getSessionFactory());
232234
}
233235

234-
public void postProcess(NativeWebRequest request, Callable<?> task, Object concurrentResult) {
235-
TransactionSynchronizationManager.unbindResource(getSessionFactory());
236+
private void initializeThread() {
237+
TransactionSynchronizationManager.bindResource(getSessionFactory(), this.sessionHolder);
236238
}
237239
}
238240

spring-orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@
3434
import org.springframework.util.StringUtils;
3535
import org.springframework.web.context.WebApplicationContext;
3636
import org.springframework.web.context.request.NativeWebRequest;
37-
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
37+
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
3838
import org.springframework.web.context.request.async.WebAsyncManager;
3939
import org.springframework.web.context.request.async.WebAsyncUtils;
4040
import org.springframework.web.context.support.WebApplicationContextUtils;
@@ -242,7 +242,7 @@ private boolean applyEntityManagerBindingInterceptor(WebAsyncManager asyncManage
242242
/**
243243
* Bind and unbind the {@code EntityManager} to the current thread.
244244
*/
245-
private static class EntityManagerBindingCallableInterceptor implements CallableProcessingInterceptor {
245+
private static class EntityManagerBindingCallableInterceptor extends CallableProcessingInterceptorAdapter {
246246

247247
private final EntityManagerFactory emFactory;
248248

@@ -254,16 +254,18 @@ public EntityManagerBindingCallableInterceptor(EntityManagerFactory emFactory, E
254254
this.emHolder = emHolder;
255255
}
256256

257-
public void preProcess(NativeWebRequest request, Callable<?> task) {
257+
@Override
258+
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
258259
initializeThread();
259260
}
260261

261-
private void initializeThread() {
262-
TransactionSynchronizationManager.bindResource(this.emFactory, this.emHolder);
262+
@Override
263+
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
264+
TransactionSynchronizationManager.unbindResource(this.emFactory);
263265
}
264266

265-
public void postProcess(NativeWebRequest request, Callable<?> task, Object concurrentResult) {
266-
TransactionSynchronizationManager.unbindResource(this.emFactory);
267+
private void initializeThread() {
268+
TransactionSynchronizationManager.bindResource(this.emFactory, this.emHolder);
267269
}
268270
}
269271

spring-orm/src/main/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewInterceptor.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
3131
import org.springframework.web.context.request.AsyncWebRequestInterceptor;
3232
import org.springframework.web.context.request.NativeWebRequest;
3333
import org.springframework.web.context.request.WebRequest;
34-
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
34+
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
3535
import org.springframework.web.context.request.async.WebAsyncManager;
3636
import org.springframework.web.context.request.async.WebAsyncUtils;
3737

@@ -163,7 +163,7 @@ private boolean applyCallableInterceptor(WebAsyncManager asyncManager, String ke
163163
/**
164164
* Bind and unbind the Hibernate {@code Session} to the current thread.
165165
*/
166-
private class EntityManagerBindingCallableInterceptor implements CallableProcessingInterceptor {
166+
private class EntityManagerBindingCallableInterceptor extends CallableProcessingInterceptorAdapter {
167167

168168
private final EntityManagerHolder emHolder;
169169

@@ -172,16 +172,18 @@ public EntityManagerBindingCallableInterceptor(EntityManagerHolder emHolder) {
172172
this.emHolder = emHolder;
173173
}
174174

175-
public void preProcess(NativeWebRequest request, Callable<?> task) {
175+
@Override
176+
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
176177
initializeThread();
177178
}
178179

179-
private void initializeThread() {
180-
TransactionSynchronizationManager.bindResource(getEntityManagerFactory(), this.emHolder);
180+
@Override
181+
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
182+
TransactionSynchronizationManager.unbindResource(getEntityManagerFactory());
181183
}
182184

183-
public void postProcess(NativeWebRequest request, Callable<?> task, Object concurrentResult) {
184-
TransactionSynchronizationManager.unbindResource(getEntityManagerFactory());
185+
private void initializeThread() {
186+
TransactionSynchronizationManager.bindResource(getEntityManagerFactory(), this.emHolder);
185187
}
186188
}
187189

spring-orm/src/test/java/org/springframework/orm/hibernate3/support/OpenSessionInViewTests.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package org.springframework.orm.hibernate3.support;
1818

19-
import static org.easymock.EasyMock.anyObject;
19+
import static org.easymock.EasyMock.*;
2020
import static org.easymock.EasyMock.createMock;
2121
import static org.easymock.EasyMock.createStrictMock;
2222
import static org.easymock.EasyMock.expect;
@@ -39,6 +39,7 @@
3939
import javax.servlet.ServletResponse;
4040
import javax.transaction.TransactionManager;
4141

42+
import org.easymock.EasyMock;
4243
import org.hibernate.FlushMode;
4344
import org.hibernate.HibernateException;
4445
import org.hibernate.SessionFactory;
@@ -63,8 +64,8 @@
6364
import org.springframework.web.context.WebApplicationContext;
6465
import org.springframework.web.context.request.ServletWebRequest;
6566
import org.springframework.web.context.request.async.AsyncWebRequest;
66-
import org.springframework.web.context.request.async.WebAsyncUtils;
6767
import org.springframework.web.context.request.async.WebAsyncManager;
68+
import org.springframework.web.context.request.async.WebAsyncUtils;
6869
import org.springframework.web.context.support.StaticWebApplicationContext;
6970

7071

@@ -177,6 +178,8 @@ public void testOpenSessionInViewInterceptorAsyncScenario() throws Exception {
177178

178179
AsyncWebRequest asyncWebRequest = createStrictMock(AsyncWebRequest.class);
179180
asyncWebRequest.addCompletionHandler((Runnable) anyObject());
181+
asyncWebRequest.setTimeoutHandler((Runnable) anyObject());
182+
asyncWebRequest.addCompletionHandler((Runnable) anyObject());
180183
asyncWebRequest.startAsync();
181184
replay(asyncWebRequest);
182185

@@ -491,6 +494,8 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
491494

492495
AsyncWebRequest asyncWebRequest = createMock(AsyncWebRequest.class);
493496
asyncWebRequest.addCompletionHandler((Runnable) anyObject());
497+
asyncWebRequest.setTimeoutHandler(EasyMock.<Runnable>anyObject());
498+
asyncWebRequest.addCompletionHandler((Runnable) anyObject());
494499
asyncWebRequest.startAsync();
495500
expect(asyncWebRequest.isAsyncStarted()).andReturn(true).anyTimes();
496501
replay(asyncWebRequest);

spring-orm/src/test/java/org/springframework/orm/jpa/support/OpenEntityManagerInViewTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -155,6 +155,8 @@ public void testOpenEntityManagerInViewInterceptorAsyncScenario() throws Excepti
155155

156156
AsyncWebRequest asyncWebRequest = createStrictMock(AsyncWebRequest.class);
157157
asyncWebRequest.addCompletionHandler((Runnable) anyObject());
158+
asyncWebRequest.setTimeoutHandler((Runnable) anyObject());
159+
asyncWebRequest.addCompletionHandler((Runnable) anyObject());
158160
asyncWebRequest.startAsync();
159161
replay(asyncWebRequest);
160162

@@ -344,6 +346,8 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
344346

345347
AsyncWebRequest asyncWebRequest = createMock(AsyncWebRequest.class);
346348
asyncWebRequest.addCompletionHandler((Runnable) anyObject());
349+
asyncWebRequest.setTimeoutHandler((Runnable) anyObject());
350+
asyncWebRequest.addCompletionHandler((Runnable) anyObject());
347351
asyncWebRequest.startAsync();
348352
expect(asyncWebRequest.isAsyncStarted()).andReturn(true).anyTimes();
349353
replay(asyncWebRequest);

spring-test-mvc/src/main/java/org/springframework/test/web/servlet/TestDispatcherServlet.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727

2828
import org.springframework.web.context.WebApplicationContext;
2929
import org.springframework.web.context.request.NativeWebRequest;
30-
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
30+
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
3131
import org.springframework.web.context.request.async.DeferredResult;
32-
import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor;
32+
import org.springframework.web.context.request.async.DeferredResultProcessingInterceptorAdapter;
3333
import org.springframework.web.context.request.async.WebAsyncManager;
3434
import org.springframework.web.context.request.async.WebAsyncUtils;
3535
import org.springframework.web.servlet.DispatcherServlet;
@@ -48,6 +48,8 @@
4848
@SuppressWarnings("serial")
4949
final class TestDispatcherServlet extends DispatcherServlet {
5050

51+
private static final String KEY = TestDispatcherServlet.class.getName() + "-interceptor";
52+
5153
/**
5254
* Create a new instance with the given web application context.
5355
*/
@@ -70,19 +72,15 @@ private CountDownLatch registerAsyncInterceptors(HttpServletRequest request) {
7072

7173
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
7274

73-
asyncManager.registerCallableInterceptor("mockmvc", new CallableProcessingInterceptor() {
74-
public void preProcess(NativeWebRequest request, Callable<?> task) throws Exception { }
75-
public void postProcess(NativeWebRequest request, Callable<?> task, Object value) throws Exception {
75+
asyncManager.registerCallableInterceptor(KEY, new CallableProcessingInterceptorAdapter() {
76+
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object value) throws Exception {
7677
asyncResultLatch.countDown();
7778
}
7879
});
79-
80-
asyncManager.registerDeferredResultInterceptor("mockmvc", new DeferredResultProcessingInterceptor() {
81-
public void preProcess(NativeWebRequest request, DeferredResult<?> result) throws Exception { }
82-
public void postProcess(NativeWebRequest request, DeferredResult<?> result, Object value) throws Exception {
80+
asyncManager.registerDeferredResultInterceptor(KEY, new DeferredResultProcessingInterceptorAdapter() {
81+
public <T> void postProcess(NativeWebRequest request, DeferredResult<T> result, Object value) throws Exception {
8382
asyncResultLatch.countDown();
8483
}
85-
public void afterExpiration(NativeWebRequest request, DeferredResult<?> result) throws Exception { }
8684
});
8785

8886
return asyncResultLatch;

0 commit comments

Comments
 (0)