Handler execution chain in Spring Web

Spring's DispatcherServlet couldn't dispatch the requests without several elements. One of the most important of them is handler execution chain.

In this article we'll focus on this famous handler execution chain. The first part will introduce us to this concept. The second part will dive us into pragmatic world of Spring's execution chain. In the last part, we'll analyze how handler execution chain is implemented in Spring's native DispatcherServlet.

What is handler execution chain in Spring ?

Handler execution chain in Spring is a kind of chain of responsibility design pattern composed by handler mapping and handler interceptors. Handler mapper is used to match current request to appropriated controller. Interceptors are the objects invoked before and after some of dispatching actions (controller resolving, view rendering etc.).

We can resume that a handler execution chain is a group of elements used by dispatcher servlet to process received request. However, all execution chain calls are made by dispatcher servlet class. The execution chain is only a kind of container which:
- defines handler mappings and interceptors
- defines the methods to apply on some moments of the dispatch (after handler adapter retreiving, after controller's method invocation etc.)

HandlerExecutionChain class

The handler execution chain is represented by org.springframework.web.servlet.HandlerExecutionChain class. Its main two private fields, Object handler and HandlerInterceptor[] interceptors, are used in request's dispatching process. The first one contains an handler object used to find the handler adapter's instance. The second one is an array containing interceptors to apply to treated request.

In DispatcherServlet class, HandlerExecutionChain retrieval is done through protected HandlerExecutionChain getHandler(HttpServletRequest request). It iterates through all available handler mappings and returns the first handler able to treat the request.

The second thing done in DispatcherServlet with HandlerExecutionChain instance is the applying of interceptors pre- and post- calls. That is translated by DispatcherServlet's methods like applyPreHandle, applyPostHandle, applyAfterConcurrentHandlingStarted and triggerAfterCompletion.

Handler execution chain use

To illustrate handler execution chain use, we'll take the custom dispatcher servlet class from the article about Spring DispatcherServlet lifecycle and add to it a customized handler execution chain. But instead of digging into all Spring's classes working with HandlerExecutionChain, we'll create a new object (DumberHandlerExecutionChain), add to it two methods to invoke interceptors and use it in DispatcherServlet's class. Let's start to code:

// we start directly by doService method which handles incoming request
// retrieve execution chain and handler adapters adapted to received request
DumberHandlerExecutionChain executionChain = new DumberHandlerExecutionChain(getHandlerExecutionChain(request));
System.out.println("Working with following handler execution chain: "+executionChain);
HandlerAdapter adapter = getHandlerAdapter(executionChain.getHandler());

if (!executionChain.preHandle(request, response)) {
	throw new IllegalStateException("Some of defined interceptors weren't ivoked correctly.");
}
// handle the request and try to generate a ModelAndView instance
ModelAndView modelView = adapter.handle(request, response, executionChain.getHandler());
if (modelView == null) {
	throw new IllegalStateException("Handled ModelAndView can't be null (handled with adapter: "+adapter+")");
}
if (!modelView.isReference()) {
	throw new UnsupportedOperationException("Only view models defined as references can be used in this servlet");
}
executionChain.postHandle(request, response, modelView);

Only 3 lines changed. The first one is the definition of DumberHandlerExecutionChain instance instead of HandlerExecutionChain. The second change is the presence of applyPreHandler and applyPostHandler methods. Realy, it's nothing complicated to understand in this code. It's a little bit more stuff in DumberHandlerExecutionChain class, defined as well:

public class DumberHandlerExecutionChain extends HandlerExecutionChain {

	public DumberHandlerExecutionChain(HandlerExecutionChain chain) {
		super(chain);
		System.out.println("Overriden constructor DumberHandlerExecutionChain invoked");
	}
	
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
		for (HandlerInterceptor interceptor : getInterceptors()) {
			System.out.println("Running pre handler for :"+interceptor);
			if (!interceptor.preHandle(request, response, this.getHandler())) {
				System.out.println("An error occured on calling handler for "+interceptor);
				return false;
			}
		}
		return true;
	}
	
	public void postHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView viewModel) throws Exception {
		for (HandlerInterceptor interceptor : getInterceptors()) {
			interceptor.postHandle(request, response, this.getHandler(), viewModel);
			System.out.println("Running post handler for :"+interceptor);
		}
	}

	@Override
	public String toString() {
		return "DumberHandlerExecutionChain {interceptors :"+Arrays.asList(this.getInterceptors())+", handler: "+this.getHandler()+"}";
	}
}

They are 2 methods mentioned previously: preHandle and postHandle. Both are similar. They start by iterate through all available interceptors. The difference is that the first one calls interceptor's preHandle method and the second one interceptor's postHandle method. The second difference is the result. preHandle returns true if all interceptors accomplished theirs operations correctly. postHandle doesn't return nothing.

But these 2 methods aren't a heart of this class. Its most important place is the constructor which calls this super constructor:

// 1. Invoked directly by super(chain) call
public HandlerExecutionChain(Object handler) {
		this(handler, null);
}

// 2. Called directly by previous constructor
public HandlerExecutionChain(Object handler, HandlerInterceptor[] interceptors) {
	if (handler instanceof HandlerExecutionChain) {
		HandlerExecutionChain originalChain = (HandlerExecutionChain) handler;
		this.handler = originalChain.getHandler();
		this.interceptorList = new ArrayList();
		CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
		CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
	}
	else {
		this.handler = handler;
		this.interceptors = interceptors;
	}
}

As we can see, thanks to handler instanceof check, we can work on HandlerExecutionChain generated natively in dispatcher servlet. We don't need to looking for handler mappings that produce HandlerExecutionChain instances (for example: org.springframework.web.servlet.handler.AbstractHandlerMapping or org.springframework.web.servlet.handler.AbstractUrlHandlerMapping implementations) and override existent code. Instead of make this complicated step, we can simply pass HandlerExecutionChain's instance to constructor of our customized execution chain class.

By doing that, you could see on your logs following entries:

Overriden constructor DumberHandlerExecutionChain invoked
Working with following handler execution chain: DumberHandlerExecutionChain {interceptors :[org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor@77f6d2e3, com.waitingforcode.interceptors.LotteryInterceptor@6d8f729c], handler: public java.lang.String com.waitingforcode.controller.TestController.test(javax.servlet.http.HttpServletRequest)}
Running pre handler for :org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor@77f6d2e3
Running pre handler for :com.waitingforcode.interceptors.LotteryInterceptor@6d8f729c
[LotteryInterceptor] preHandle
Controller asks, are you a lottery winner ? true
Current locale is :org.springframework.web.servlet.DispatcherServlet$1@5cf346dc
Request attributes are :org.apache.catalina.connector.RequestFacade@7d9ccb73
Running post handler for :org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor@77f6d2e3
[LotteryInterceptor] postHandle
Running post handler for :com.waitingforcode.interceptors.LotteryInterceptor@6d8f729c

In this article we have seen the concept of handler execution chain in Spring dispatcher servlet. We have learned that it contains not only handler mappings (used after to retreive handler adapters), but interceptors invoked at different time too. Next, we've analyzed HandlerExecutionChain class more in detail. We've discovered two principal private fields from those one was a handler and the other an array of interceptors. At the last part we've pass to code by writting our own handler execution chain able to call interceptors before and after handler adapter's action.


If you liked it, you should read:

📚 Newsletter Get new posts, recommended reading and other exclusive information every week. SPAM free - no 3rd party ads, only the information about waitingforcode!