We saw in the last tutorial, using AsyncHandlerInterceptor was a way to intercept async processing.
To have more interceptions around user defined 'Callable' process, we can register CallableProcessingInterceptor
Let's understand that with an example. We going to modify the previous tutorial example to see a clear difference between the two.
Creating CallableProcessingInterceptor
package com.logicbig.example;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.async.CallableProcessingInterceptor;
import java.util.concurrent.Callable;
public class MyCallableProcessingInterceptor implements
CallableProcessingInterceptor {
@Override
public <T> void beforeConcurrentHandling (
NativeWebRequest request,
Callable<T> task) throws Exception {
System.out.println("callableInterceptor#beforeConcurrentHandling called. " +
"Thread: " + Thread.currentThread().getName());
}
@Override
public <T> void preProcess (
NativeWebRequest request,
Callable<T> task) throws Exception {
System.out.println("callableInterceptor#preProcess called. "+
" Thread: " + Thread.currentThread().getName());
}
@Override
public <T> void postProcess (NativeWebRequest request,
Callable<T> task,
Object concurrentResult) throws Exception {
System.out.println("callableInterceptor#postProcess called. "+
" Thread: " + Thread.currentThread().getName());
}
@Override
public <T> Object handleTimeout (NativeWebRequest request,
Callable<T> task) throws Exception {
System.out.println("callableInterceptor#handleTimeout called."+
" Thread: " + Thread.currentThread().getName());
return RESULT_NONE;
}
@Override
public <T> void afterCompletion (NativeWebRequest request,
Callable<T> task) throws Exception {
System.out.println("callableInterceptor#afterCompletion called."+
" Thread: " + Thread.currentThread().getName());
}
}
Registering the interceptor
We can register the above interceptor in the HandlerInterceptor#preHandle method on the fly. We are going to modify our previous example MyAsyncHandlerInterceptor a little for that:
package com.logicbig.example;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyAsyncHandlerInterceptor extends HandlerInterceptorAdapter {
private static final Object CALLABLE_INTERCEPTOR_KEY = new Object();
@Override
public boolean preHandle (HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
System.out.println("interceptor#preHandle called." +
" Thread: " + Thread.currentThread()
.getName());
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(CALLABLE_INTERCEPTOR_KEY,
new MyCallableProcessingInterceptor());
return true;
}
.......
}
The controller and the main classes are same as our last example. On running the main class and accessing the application in the browser. We will have following output:
interceptor#preHandle called. Thread: http-nio-8080-exec-1
controller#handler called. Thread: http-nio-8080-exec-1
controller#handler finished
callableInterceptor#beforeConcurrentHandling called. Thread: http-nio-8080-exec-1
interceptor#afterConcurrentHandlingStarted called. Thread: http-nio-8080-exec-1
callableInterceptor#preProcess called. Thread: MvcAsync1
controller-callable#async task started. Thread: MvcAsync1
controller-callable#async task finished
callableInterceptor#postProcess called. Thread: MvcAsync1
interceptor#preHandle called. Thread: http-nio-8080-exec-2
interceptor#postHandle called. Thread: http-nio-8080-exec-2
interceptor#afterCompletion called Thread.: http-nio-8080-exec-2
callableInterceptor#afterCompletion called. Thread: http-nio-8080-exec-2
Here we can see that CallableProcessingInterceptor is integrated more deeply with the lifecycle of an asynchronous request.
Here's the flow diagram to see a clear difference from the last example:
Example ProjectDependencies and Technologies Used: - Spring Boot 1.4.2.RELEASE
Corresponding Spring Version 4.3.4.RELEASE - Spring Boot Web Starter : Starter for building web, including RESTful, applications using Spring
MVC. Uses Tomcat as the default embedded container.
- JDK 1.8
- Maven 3.3.9
|