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
This commit is contained in:
Rossen Stoyanchev
2012-10-26 17:55:28 -04:00
parent 06e34f05a6
commit f036ed639f
23 changed files with 860 additions and 333 deletions

View File

@@ -34,7 +34,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
import org.springframework.util.Assert;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;
@@ -318,7 +318,7 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
/**
* Bind and unbind the Hibernate {@code Session} to the current thread.
*/
private static class SessionBindingCallableInterceptor implements CallableProcessingInterceptor {
private static class SessionBindingCallableInterceptor extends CallableProcessingInterceptorAdapter {
private final SessionFactory sessionFactory;
@@ -329,17 +329,19 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
this.sessionHolder = sessionHolder;
}
public void preProcess(NativeWebRequest request, Callable<?> task) {
@Override
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
initializeThread();
}
@Override
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
}
private void initializeThread() {
TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder);
}
public void postProcess(NativeWebRequest request, Callable<?> task, Object concurrentResult) {
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
}
}
}

View File

@@ -29,7 +29,7 @@ import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.AsyncWebRequestInterceptor;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
@@ -276,7 +276,7 @@ public class OpenSessionInViewInterceptor extends HibernateAccessor implements A
/**
* Bind and unbind the Hibernate {@code Session} to the current thread.
*/
private class SessionBindingCallableInterceptor implements CallableProcessingInterceptor {
private class SessionBindingCallableInterceptor extends CallableProcessingInterceptorAdapter {
private final SessionHolder sessionHolder;
@@ -284,16 +284,18 @@ public class OpenSessionInViewInterceptor extends HibernateAccessor implements A
this.sessionHolder = sessionHolder;
}
public void preProcess(NativeWebRequest request, Callable<?> task) {
@Override
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
initializeThread();
}
@Override
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
TransactionSynchronizationManager.unbindResource(getSessionFactory());
}
private void initializeThread() {
TransactionSynchronizationManager.bindResource(getSessionFactory(), this.sessionHolder);
}
public void postProcess(NativeWebRequest request, Callable<?> task, Object concurrentResult) {
TransactionSynchronizationManager.unbindResource(getSessionFactory());
}
}
}

View File

@@ -34,7 +34,7 @@ import org.springframework.orm.hibernate4.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;
@@ -215,7 +215,7 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
/**
* Bind and unbind the Hibernate {@code Session} to the current thread.
*/
private static class SessionBindingCallableInterceptor implements CallableProcessingInterceptor {
private static class SessionBindingCallableInterceptor extends CallableProcessingInterceptorAdapter {
private final SessionFactory sessionFactory;
@@ -226,16 +226,18 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
this.sessionHolder = sessionHolder;
}
public void preProcess(NativeWebRequest request, Callable<?> task) {
@Override
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
initializeThread();
}
@Override
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
}
private void initializeThread() {
TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder);
}
public void postProcess(NativeWebRequest request, Callable<?> task, Object concurrentResult) {
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
}
}
}

View File

@@ -33,7 +33,7 @@ import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.AsyncWebRequestInterceptor;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
@@ -215,7 +215,7 @@ public class OpenSessionInViewInterceptor implements AsyncWebRequestInterceptor
/**
* Bind and unbind the Hibernate {@code Session} to the current thread.
*/
private class SessionBindingCallableInterceptor implements CallableProcessingInterceptor {
private class SessionBindingCallableInterceptor extends CallableProcessingInterceptorAdapter {
private final SessionHolder sessionHolder;
@@ -223,17 +223,19 @@ public class OpenSessionInViewInterceptor implements AsyncWebRequestInterceptor
this.sessionHolder = sessionHolder;
}
public void preProcess(NativeWebRequest request, Callable<?> task) {
@Override
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
initializeThread();
}
@Override
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
TransactionSynchronizationManager.unbindResource(getSessionFactory());
}
private void initializeThread() {
TransactionSynchronizationManager.bindResource(getSessionFactory(), this.sessionHolder);
}
public void postProcess(NativeWebRequest request, Callable<?> task, Object concurrentResult) {
TransactionSynchronizationManager.unbindResource(getSessionFactory());
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 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.
@@ -34,7 +34,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
import org.springframework.util.StringUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;
@@ -242,7 +242,7 @@ public class OpenEntityManagerInViewFilter extends OncePerRequestFilter {
/**
* Bind and unbind the {@code EntityManager} to the current thread.
*/
private static class EntityManagerBindingCallableInterceptor implements CallableProcessingInterceptor {
private static class EntityManagerBindingCallableInterceptor extends CallableProcessingInterceptorAdapter {
private final EntityManagerFactory emFactory;
@@ -254,17 +254,19 @@ public class OpenEntityManagerInViewFilter extends OncePerRequestFilter {
this.emHolder = emHolder;
}
public void preProcess(NativeWebRequest request, Callable<?> task) {
@Override
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
initializeThread();
}
@Override
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
TransactionSynchronizationManager.unbindResource(this.emFactory);
}
private void initializeThread() {
TransactionSynchronizationManager.bindResource(this.emFactory, this.emHolder);
}
public void postProcess(NativeWebRequest request, Callable<?> task, Object concurrentResult) {
TransactionSynchronizationManager.unbindResource(this.emFactory);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2012 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.
@@ -31,7 +31,7 @@ import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.AsyncWebRequestInterceptor;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
@@ -163,7 +163,7 @@ public class OpenEntityManagerInViewInterceptor extends EntityManagerFactoryAcce
/**
* Bind and unbind the Hibernate {@code Session} to the current thread.
*/
private class EntityManagerBindingCallableInterceptor implements CallableProcessingInterceptor {
private class EntityManagerBindingCallableInterceptor extends CallableProcessingInterceptorAdapter {
private final EntityManagerHolder emHolder;
@@ -172,17 +172,19 @@ public class OpenEntityManagerInViewInterceptor extends EntityManagerFactoryAcce
this.emHolder = emHolder;
}
public void preProcess(NativeWebRequest request, Callable<?> task) {
@Override
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
initializeThread();
}
@Override
public <T> void postProcess(NativeWebRequest request, Callable<T> task, Object concurrentResult) {
TransactionSynchronizationManager.unbindResource(getEntityManagerFactory());
}
private void initializeThread() {
TransactionSynchronizationManager.bindResource(getEntityManagerFactory(), this.emHolder);
}
public void postProcess(NativeWebRequest request, Callable<?> task, Object concurrentResult) {
TransactionSynchronizationManager.unbindResource(getEntityManagerFactory());
}
}
}