---
title: 'Sums up servlet lifecycle, with AOP perspective'
disqus: hackmd
---
Sums up servlet lifecycle, with AOP perspective
===



[TOC]
## Abstract
The discussion would end up with two topics:
- Request/Response lifecycle upon springboot-framework servlet
- Disect the subtle differences between such AOP concepts in Java as Filter, Interceptor and AOP aspect.
Before getting in into two topics mentioned above, we should introduce servlet for comprehensiveness in advance even though it's cliche. \
Then, given the servlet framework upon springboot, completed lifecycle of request would be splitted by the pivot into 2 parts in favor of increasing the fluency of flow we're going to discuss, the pivot called **servlet container**. \
The context would head forward to the conclusion following 3 steps below:
1. What task will be done on the server side after the Web Container(Tomcat) receives the request sent from web page, percisely called Client?
2. How do the request and response be "encapulated" and conveyyed around the inside and outside of the servlet container?
3. How to dispatch the request sent into servlet container to the coresponding servlet application?
Besides, the configuration issue on handlerMapping or handlerAdapter however would not be addressed. The deployment of AOPs and the mechanism of them within the servlet application are the most intriguinig topics that I would like to share with you.
Further, this guide would go through the whole lifecycle outside/inside the servlet by depicting a user story, Having Tattoo, in the meanwhile introducing such various AOP concepts often implemented in Java as Filter, Interceptor and AOP aspect, each of section attached with codes and the running results.
## What is servlet
#### A Java component offering service tackling with HttpRequest/Response
As an intermediate component, SERVLET is an application bridging web explorer or other clients sending message end and service from server end for conveying response and request.
#### For interacting in dynamic(real time) with client
Compared to the static web page scripted in Html, css and JavaScript, dynamic web page could interact with client in real time as the servlet comes into play.
## Web Container(Tomcat) handling the request
#### Tomcat as web container must transfer HttpRequest into the correct servlet application
The ultimate goal of the client sending request is getting a expected response, with a process in which the application server handles dozens of business logics. To attain the final destination, Tomcat would be required to instantiate and load the correct servlet, parametize the request encapsulated and response moduled, and finally deliver them into the target servlet.
```sequence
Client->Tomcat: send HTTPRequest
Note over Tomcat, Servlet: instantiate the servlet
Note over Tomcat: encapsulate into ServletRequest
Tomcat->Servlet: send ServletRequest
Note over Servlet: hanlding business logic
Servlet->Tomcat: send ServletResponse
Note over Tomcat: transform into HttpResponse
Tomcat->Client: send HTTPResponse
```
However, then a question raised is how do Web Container load the corresponding servlet?
#### Reflecting the Url, with SpringBootServletInitializer
There are two ways to find servlet and reflect the url, where the second way is what we concern (as springboot framwork is the scope of this topic):
- (general in Java web) Reflect the servlet setting configured in web.xml.
- (Springboot) Instantiate the Java class - SpringBootServletInitializer - before running time.
It's cliche but important to metion that the feature of auto-configuration springboot has should be iterated. Because of the trait we mention many times, springbootServletInitializer has set up all the default configuration you need to deal with basic mapping, implementing the interface - WebApplicationInitializer - with overridden method, the method that keeps listening, technically called observing, the request since the server was on.
```java=
public abstract class SpringBootServletInitializer
implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
//register a listener with a default context(setting)
}
}
```
Thus, the listener would complete the task as same as that web.xml has done, receiving the request and find the corrsponding servlet. New servlet would be instantiate if it was the first time being called, otherwise the servlet container would return an existed serlet having been called beforehand.
So far, we've known how and when Web container builds up a servlet. Nevertheless, the accompanied issue appears as long as the servlet is loaded : **How would the request be handled** in the servlet just loaded?
## DispatcherServlet comes into play
After the servlet is built up, it needs a player to arrange the channel for various requesting type, which could be GET, POST, PUT or other else, a player named dispatcherServlet.
DispatcherServlet is a servlet class in which doDispatch() method has already been implemented. doDispatch() mainly deals with the calling of interceptor and handler. In other words, find the target controller and put the request in. Here is the summary of what doDispatch() has done for dispatching:
```sequence
DispatcherServlet->handlerMapping:
handlerMapping->DispatcherServlet: return a executionChain
DispatcherServlet-->Interceptor:
Interceptor->Handler:
Note over Handler: do business logic
Handler->Interceptor:
Note left of Interceptor: Interceptor: afterCompletion
Interceptor-->DispatcherServlet: feedback response
```
1. getting handler through handlerMappings
2. getting handlerAdapter
3. apply pre-handelr of interceptor in execChain, provided through step1.
4. apply handler
5. apply post-handler
```java=
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// -------------------------------------------step1
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// -------------------------------------------step2
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// -------------------------------------------step3
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// -------------------------------------------step4 : the breakpoint invoking the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
// -------------------------------------------step5
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception ex) {
dispatchException = ex;
} catch (Throwable err) {
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
} catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
} catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
```
In short, the dispatcherServlet is responsible for reflecting correct handler(controller) by calling handler mapping, which is auto-configured as well.
#### A pause from discussing Lifecycle
So far, we've observed the lifecycle traversing in a basic perspective from Web container to the handler that the request targets. Before we stride to the next step, let's take a retrospect on keypoints just mentioned above :
1. Tomcat as a web Container is in charge of instantiating corresponding servlet.
2. After servlet was loaded, Tomcat parametizes the encapsulated ServletRequest/Response and sends them into servlet in which service() has been auto-configured.
3. Inheritting the service() method, DispatcherServlet hands over the request to the target handler by getting instance from handlermapping.
Yet it's not the end, the essential framework we protrayed is all for another greater canvas. In terms of AOP concepts, request should have gone through 3 "cuts" that we haven't mentioned in the sequence we framed, the cuts that also play an important role on lifecycle of request.
## Where do AOP play in the request lifecycle
With a whole picture understanding how Request would be dispatched, the last part would address what "aspect" would be gone through before the request attains the handler(controller), focusing on discussing discrepency between 3 kinds of AOP implementation:
- Filter
- Interceptor
- AOP
```sequence
Note over Container: transform into HttpRequest
Container->Filter:
Note over Filter: do filter
Filter->DispatcherServlet:
Note over DispatcherServlet: do handler mapping
DispatcherServlet->Interceptor:
Note over Interceptor: do preHandle
Interceptor->handler:
Note over handler: controller handling business
Note over handler: AOP enhancement
handler->Interceptor:
Note over Interceptor: do postHandle
Interceptor-->Container: response
Note over Container: transform into HttpResponse
```
#### An story analogous to lifecycle
Given a story that a customer plans to tattoo a butterfly pattern. With mandotory limitation, the customer must have the membership to qualify for the service. Beside, the store implements a check-out-first policy, charging the service fee before tattooing.
Speaking to the discount, you can buy one get one free if the customer is a newcomer.
Then now, we could get in the process of tattoo. Before getting it started, the store notices that the bonus that every custormer possesses is that the natural background comes with the insect tattoo.
At last, all the customer has to do is waiting until the process finishes.
### Filter
#### Chapter in the story
The front-desk is going to validate the membership of the client...
#### Characteristics
- Focus on coarse-grained task : Authentication
- logging and auditing
- Decouple any functionality from spring framework.
#### Register process
1. implement interface - Filter
2. register as a Bean annotated with @Configuration
```java=
@Slf4j
public class TattooFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("validate membership for having tattoo.");
//filter request
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
//filter response
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
httpResponse.reset();
httpResponse.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
httpResponse.getWriter()
.print(new ObjectMapper()
.writeValueAsString("response went through filter"));
httpResponse.getWriter().flush();
filterChain.doFilter(servletRequest, servletResponse);
}
}
```
```java=
@Configuration
public class BeanRegisterConfig {
@Bean
public FilterRegistrationBean filterRegistration(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new TattooFilter());
registrationBean.setName("TattooFilter");
registrationBean.addUrlPatterns("/tattoo"); //intercept the defined url pattern
registrationBean.setOrder(1); //ranks higher priorty as number gets smaller
return registrationBean;
}
}
```
### Interceptor
#### Chapter in the story
1. Formulating the check-out-first poicy, the store has to check the payment. in advance before service.
2. Check if the customer qualifies for the favor - buy one get one free.
#### Characteristic
- Deal with fine-grained task : more detailed authentication.
- Enable to handling cross-cutting concerns : logging, pre/post-handle .
- Manipulating spring context and model.
>reminder : Conceptually different from @exceptionHandler, which is more closed to AOP class. (refer to the Annotation @RestControllerAdvice.)
#### Register process:
1. Implement interface - HandlerInterceptor
2. register a bean implementing interface - WebMvcConfigurer
#### The deployment of multi-Interceptor
```sequence
Note over DispatcherServlet: do handlerMapping
DispatcherServlet->Interceptor1: executionChain
Note over Interceptor1: do preHandle1
Interceptor1->Interceptor2:
Note over Interceptor2: do preHandle2
Interceptor2->Handler:
Handler->Interceptor2:
Note over Interceptor2: do postHandle2
Interceptor2->Interceptor1:
Note over Interceptor1: do postHandle1
Note right of DispatcherServlet: do afterCompletion1
Note right of DispatcherServlet: do afterCompletion2
Interceptor1->DispatcherServlet:
```
```java=
@Slf4j
public class PaymentValidInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("preHandle1 : check out the payment");
// If returns false, deliver to errorhandling.
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle1 : checked");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("Interceptor1 completed");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
```
```java=
@Slf4j
public class DiscountInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("preHandle2 : buy one get one free?");
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle2 : done with 2 identical design");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("Interceptor2 completed");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
```
```java=
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
String[] addPathPatterns = {"/**"};
String[] excludePathPatterns = {};
//get more outlying when the object is added earlier.
registry.addInterceptor(new BackgroundInterceptor())
.addPathPatterns(addPathPatterns)
.excludePathPatterns(excludePathPatterns);
registry.addInterceptor(new PolishInterceptor())
.addPathPatterns(addPathPatterns)
.excludePathPatterns(excludePathPatterns);
}
}
```
### AOP
---
#### Chapter in the story
The butterfly tatoo comes with a free natural background as long as the type of pattern requested is insect.
#### Characteristics
- Decoupling.
- Being enable to enhance certain type of business logic.
- Logging and auditing.
#### AOP stresses on enhancement on the business logic
As the "aspect" performs in the tattoo example, the advice effects the certain type of function by weaving, cofining the methods in classes that are designed to be enhanced. The regular expression given for @Poincut clarifies the cut for which the specific set of functions should apply.
```sequence
Anywhere->Advice: request
Note over Advice: @Before
Note over Advice, Target methods: weaved
Note over Advice: @After
Advice->Anywhere: response
```
@pointcut weaves the advice into the target sets of methods, which in this case are defined in **Insect**, shown below, class, by declaring a [regular expression](https://www.baeldung.com/spring-aop-pointcut-tutorial).


:::info
Digression : Based on the [dynamic proxies](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop-introduction-proxies), AOP is not valid for static method.
:::
```java=
@Slf4j
@Aspect
@Component
@Order(1)
public class InsectBackgroundAspect {
//declaring regular expression
@Pointcut(value = "execution(* com..service.Insect.*(..))")
public void tattooPointCut(){}
@Before("tattooPointCut()")
public void doBefore(){
log.info("Aspect before : coming with a natural background");
}
@After("tattooPointCut()")
public void doAfter(){
log.info("Aspect After : frame it up!");
}
}
```
### Comparsion of 3 Aop

Highlightening the AOP section, screenshot above presents the result running whole lifecycle.
The discrepency between filter and interceptor is more clear than that between interceptor and AOP advice. We can easily discern filter and interceptor by scaling the magnitude of tasks. However, we should measure the odds in terms of the design idea that designer would like to convey.
Implementing interceptive concept in 3 different ways presents distinct intention of designing from engineer. Interceptor is often used to **INTERCEPT**; while on the other hand, AOP advice is aming for **ENHANCEMENT**. Therefore, hybridizing 3 types of aop concept would hazard the maintainability as the your colleauge have trouble comprehending the intention of design. For example, it could be weird if the task for painting background were placed to the position on which authentication should have been, vice versa.
In conclusion, even though they could be alternatively utilized on most scenario might identical to each other, such indulgent design should have to be avoided. The most important task all engineers must break down is clarifying the intention of your design.
## Appendix and FAQ
:::info
**Find this document incomplete?** Leave a comment!
:::
###### tags: `springboot` `servlet` `AOP` `Interceptor` `Filter`