Spring MVC Interceptor using HandlerInterceptorAdapter Example

Spring MVC Interceptor using HandlerInterceptorAdapter Example

Spring provides a powerful request handling mechanism which includes the ability to intercept requests before they are processed by the controllers by using handler interceptors. These interceptors are used to apply some type of processing to the requests either before, after or after the complete request finished executing.

Getting Started using Spring MVC Interceptor

In order to run this tutorial yourself, you will need the following:

Required Libraries

Copy all of the following jars to WEB-INF/lib folder of the current project. Once that has been done you should be able to verify that all of the jar files are included in your project by using the Java Build Path, Libraries tab.

interceptor_jars
aopalliance-1.0.jar
aspectjrt-1.6.10.jar
commons-logging-1.2.jar
jackson-core-asl-1.9.13.jar
jackson-mapper-asl-1.9.13.jar
log4j-1.2.17.jar
slf4j-api-1.7.10.jar
slf4j-simple-1.7.10.jar
spring-aop-4.0.6.RELEASE.jar
spring-aspects-4.0.6.RELEASE.jar
spring-beans-4.0.6.RELEASE.jar
spring-context-4.0.6.RELEASE.jar
spring-core-4.0.6.RELEASE.jar
spring-data-commons-1.10.0.RELEASE.jar
spring-data-mongodb-1.6.1.RELEASE.jar
spring-expression-4.0.6.RELEASE.jar
spring-test-4.0.6.RELEASE.jar
spring-tx-4.0.6.RELEASE.jar
spring-web-4.0.6.RELEASE.jar
spring-webmvc-4.0.6.RELEASE.jar

Complete Project Overview

I have added the project overview to give you a full view of the structure and show you all files contained in this sample project.

spring_mvc_interceptor_proj

Spring MVC Archtecture with Regards to HandlerInterceptor

Spring interceptors implement the HandlerInterceptor interface from the org.springframework.web.servlet package.

Spring provides an adapter class called HandlerInterceptorAdapter which allows us to implement only the methods you wish to depending on whether you wish to perform some preprocessing or postprocessing or both on the requests.

spring_interceptor

HandlerInterceptor Methods

  • boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) intercepts the request before reaching the handler method. This method returns a boolean. If true, it allows the request to continue in the execution chain for either another interceptor to process or for the the handler itself. If false, Spring assumes the interceptor has processed the request and interrupts any future execution in the execution chain including the actual handler. At this point, our controller will never process this request.
  • void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) actually sits in between the HandlerAdapter and before DispatcherServlet renders the view allowing the interceptor to inject additional attributes into ModelAndView objects.

    Note: This method will be invoked on each interceptor in the chain in reverse order, so the first interceptor will be the last to be invoked.

  • void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) is called after request has completed processing. Typically this method may be used to perform some type of cleanup of resources.

    Note: This method will be invoked on each interceptor in the chain in reverse order, so the first interceptor will be the last to be invoked.

GreenZoneInterceptor Class (GreenZoneInterceptor.java)

package com.avaldes.util;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class GreenZoneInterceptor extends HandlerInterceptorAdapter {
 private boolean isGreenZone = false;
 private String greenZoneURL
            = "/SpringMVCInterceptorExample/greenzone.html";

 private static final Logger logger
         = LoggerFactory.getLogger(GreenZoneInterceptor.class);

 public void setGreenZone(boolean isGZ) {
  isGreenZone = isGZ;
 }

 public boolean isGreenZone() {
  return isGreenZone;
 }

 public String getGreenZoneURL() {
  return greenZoneURL;
 }

 public void setGreenZoneURL(String greenZoneURL) {
  this.greenZoneURL = greenZoneURL;
 }

 public boolean preHandle(HttpServletRequest request,
   HttpServletResponse response, Object handler) throws Exception {

  logger.info("Inside GreenZoneInterceptor preHandle...");
  if (isGreenZone) {
   logger.info("Inside GreenZone, redirecting to " + greenZoneURL);
   response.sendRedirect(greenZoneURL);
  }

  return true;
 }

 public void postHandle(HttpServletRequest request,
      HttpServletResponse response,
      Object handler,
      ModelAndView modelAndView) throws Exception {

  logger.info("Inside GreenZoneInterceptor postHandle...");
 }

 public void afterCompletion(HttpServletRequest request,
         HttpServletResponse response, Object handler,
         Exception ex) throws Exception {

  logger.info("Inside GreenZoneInterceptor afterCompletion...");
 }
}

Spring MVC Rest Controller (RestController.java)

package com.avaldes.tutorial;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.avaldes.model.Person;
import com.avaldes.model.RestResponse;
import com.avaldes.util.ApplicationContextProvider;
import com.avaldes.util.GreenZoneInterceptor;

@Controller
public class RestController {

 private static final Logger logger
                        = LoggerFactory.getLogger(RestController.class);

 private Map<Integer, Person> persons = new HashMap<Integer, Person>();
 private GreenZoneInterceptor interceptor;
 public static final String APPLICATION_JSON = "application/json";
 public static final String APPLICATION_XML = "application/xml";
 public static final String APPLICATION_HTML = "text/html";

 public RestController() {
  interceptor = (GreenZoneInterceptor) ApplicationContextProvider
    .getApplicationContext().getBean("greenzoneInterceptor");

  // preinitialize the list of persons available...
  persons.put(1, new Person(1, "Amaury", "Valdes",
    "100 Main Street", "Waco", "Texas", "76701"));

  persons.put(2, new Person(2, "John", "Phillips",
    "24 Linden Avenue", "Waco", "Texas", "76701"));

  persons.put(3, new Person(3, "Lisa", "McDowell",
    "8821 Flag Way", "Waco", "Texas", "76701"));
 }

 @RequestMapping(value = "/status",
   method = RequestMethod.GET, produces = APPLICATION_HTML)
 public @ResponseBody String status() {
  return "RestController OK...";
 }

 @RequestMapping(value = "/setGreenZone", method = RequestMethod.GET)
 public @ResponseBody String setGreenZone(
                @RequestParam("value") String value) {

  if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes")
    || value.equalsIgnoreCase("1")) {
   interceptor.setGreenZone(true);
   return "GreenZone has been enabled..";
  } else {
   interceptor.setGreenZone(false);
  }
  return "GreenZone has NOT been enabled.";
 }

 @RequestMapping(value="/hello", method=RequestMethod.GET)
 public ModelAndView myWelcome() {
  logger.info("Inside myHelloWorld() method...");

  ModelAndView model = new ModelAndView("welcome");
  model.addObject("message", "Welcome to the SpringMVCInterceptorExample");

  return model;
 }

 @RequestMapping(value="/persons", method=RequestMethod.GET)
 @ResponseBody
 public List<Person> getAllPersons() {
  logger.info("Inside getAllPersons() method...");

  return new ArrayList<Person>(persons.values());
 }

 @RequestMapping(value="/personById", method=RequestMethod.GET)
 @ResponseBody
 public Person getPersonById(@RequestParam("id") int id) {
  logger.info("Inside getPersonById() method...");

  Person person = persons.get(id);

  if (person != null) {
   logger.info(
     "Inside getPersonById, returned: " + person.toString());
  } else {
   logger
     .info("Inside getPersonById, ID: " + id + ", NOT FOUND!");
  }
  return person;
 }

 @RequestMapping(value="/person/add", method=RequestMethod.POST)
 @ResponseBody
 public RestResponse addPerson(
   @RequestParam("id") String id, @RequestBody Person p) {
  RestResponse response;

  logger.info("Inside addPerson, details: "
    + p.toString());

  if (id == null) {
   response = new RestResponse(false, "ID may not be null.");
   return response;
  }

  int idValue = 0;
  try {
   idValue = Integer.parseInt(id);
   persons.put(idValue, p);
   response = new RestResponse(true,
      String.format("Successfully added Person (%d) %s %s",
         p.getId(), p.getFirstName(), p.getLastName()));

  } catch (NumberFormatException e) {
   response = new RestResponse(false,
            "Unable to add Person with ID: " + id);
  }
  return response;
 }
}

ApplicationContextProvider (ApplicationContextProvider.java)

package com.avaldes.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class ApplicationContextProvider
              implements ApplicationContextAware {

  private static ApplicationContext applicationContext = null;
  private static final Logger logger
     = LoggerFactory.getLogger(ApplicationContextProvider.class);

  public static ApplicationContext getApplicationContext() {
    return applicationContext;
  }

  public void setApplicationContext(ApplicationContext ctx)
                     throws BeansException {
    applicationContext = ctx;
    logger.info("Setting App Context: "+ ctx);
  }
}

Spring Dispatcher Configuration (dispatcher-servlet.xml)

Modify the dispatcher-servlet.xml and add the necessary interceptor to the mvc:interceptors element. Use the mvc:interceptor element and add the appropriate mvc:mapping to ensure that the interceptor is mapped to anything that matches the path pattern. Subsequently, you may exclude certain path patterns from the interceptor and avoid any type of processing.

In this example, we are including all RESTful API URIs as evidenced by the path=”/**” pattern. However, we are excluding paths matching /persons/** and /setGreenZone** from any processing by the GreenZoneInterceptor class. This will allow us to set up the maintenance window in our Spring application and disable all APIs when the greenZone flag is set to true except the ones matching our exclude pattern.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:mvc="http://www.springframework.org/schema/mvc"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

 <!-- Enables the Spring MVC @Controller programming model -->
 <mvc:annotation-driven />

 <!-- Handles HTTP GET requests for /resources/** by efficiently serving
  up static resources in the ${webappRoot}/resources directory -->
 <mvc:resources mapping="/resources/**" location="/resources/" />

 <bean name="applicationContext"
    class="com.avaldes.util.ApplicationContextProvider"/>

 <bean name="greenzoneInterceptor"
    class="com.avaldes.util.GreenZoneInterceptor"/>

 <mvc:interceptors>
  <mvc:interceptor>
    <mvc:mapping path="/**" />
    <mvc:exclude-mapping path="/persons/**" />
    <mvc:exclude-mapping path="/setGreenZone**" />
    <ref bean="greenzoneInterceptor" />
  </mvc:interceptor>
 </mvc:interceptors>

 <context:component-scan base-package="com.avaldes" />

 <bean id="viewResolver"
   class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
   <property name="prefix">
     <value>/WEB-INF/</value>
   </property>

   <property name="suffix">
     <value>.jsp</value>
   </property>
  </bean>
</beans>

log4j Configuration (log4j.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC
   "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration debug="true"
	xmlns:log4j="http://jakarta.apache.org/log4j/">

	<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
  <param name="Target" value="System.out" />
  <layout class="org.apache.log4j.PatternLayout">
    <param
    name="ConversionPattern"
    value="%d{dd-MMM-yyyy HH:mm:ss.SSS} %-5p %-5l: %c - %m%n" />
  </layout>
</appender>

<appender name="fileAppender" class="org.apache.log4j.RollingFileAppender">
  <param name="append" value="false" />
  <param name="maxFileSize" value="10MB" />
  <param name="maxBackupIndex" value="10" />
  <param name="File" value="/local1/logs/SpringMVCInterceptorExample.log" />
  <layout class="org.apache.log4j.PatternLayout">
    <param
      name="ConversionPattern"
      value="%d{dd-MMM-yyyy HH:mm:ss.SSS} %-5p %-5l: %c - %m%n" />
  </layout>
</appender>

<!-- Application Loggers -->
<logger name="com.avaldes.tutorial.*">
	<level value="DEBUG" />
	<appender-ref ref="fileAppender" />
</logger>

<logger name="org.springframework.beans.*">
	<level value="INFO" />
	<appender-ref ref="fileAppender" />
</logger>

<!-- Root Logger -->
<root>
	<priority value="info" />
	<appender-ref ref="fileAppender" />
</root>
</log4j:configuration>

Person Model Class (Person.java)

package com.avaldes.model;

public class Person {
 private int id;
 private String firstName;
 private String lastName;
 private String address;
 private String city;
 private String state;
 private String zipCode;

 public Person() {};

 public Person(int id, String firstName,
   String lastName, String address,
   String city, String state, String zipCode) {

  this.id = id;
  this.firstName = firstName;
  this.lastName = lastName;
  this.address = address;
  this.city = city;
  this.state = state;
  this.zipCode = zipCode;
 }

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 public String getAddress() {
  return address;
 }

 public void setAddress(String address) {
  this.address = address;
 }

 public String getCity() {
  return city;
 }

 public void setCity(String city) {
  this.city = city;
 }

 public String getState() {
  return state;
 }

 public void setState(String state) {
  this.state = state;
 }

 public String getZipCode() {
  return zipCode;
 }

 public void setZipCode(String zipCode) {
  this.zipCode = zipCode;
 }

 @Override
 public String toString() {
  return "Person [id=" + id + ", firstName=" + firstName
    + ", lastName=" + lastName + ", address=" + address
    + ", city=" + city + ", state=" + state + ", zipCode="
    + zipCode + "]";
 }
}

RestResponse Model Class (RestResponse.java)

package com.avaldes.model;

public class RestResponse {
 private boolean success;
   private String message;

   public RestResponse(boolean success, String message) {
     this.success = success;
     this.message = message;
   }

   public boolean isSuccess() {
     return success;
   }

   public void setSuccess(boolean success) {
     this.success = success;
   }

   public String getMessage() {
    return message;
   }

   public void setMessage(String message) {
     this.message = message;
   }
}

Output from Spring MVC Interceptor

Download the Complete Source Code

That’s It!

I hope you enjoyed this tutorial. It was certainly a lot of fun putting it together and testing it out. Please continue to share the love and like us so that we can continue bringing you quality tutorials. Happy Coding!!!

spring_mvc_interceptors

Related Spring Posts

  • Creating Hello World Application using Spring MVC on Eclipse IDE
    In this tutorial we will go into some detail on how to set up your Eclipse IDE environment so that you can develop Spring MVC projects. In this post, we will create our first Spring MVC project with the all to familiar “Hello World” sample program.
  • Spring MVC Form Handling Example
    The following tutorial will guide you on writing a simple web based application which makes use of forms using Spring Web MVC framework. With this web application you will be able to interact with the customer entry form and enter all of the required values and submit them to the backend processes. I have taken the liberty of using CSS to beautify and transform the HTML page from a standard drab look and feel to a more appealing view.
  • Spring @RequestHeader Annotation Example
    In this tutorial, we will discuss the different ways that Spring MVC allow us to access HTTP headers using annotation. We will discuss how to access individual header fields from the request object as well accessing all the headers by supplying Map and then iterating through the LinkedHashMap collection. We will also show you how to set the headers in the response object.
  • Spring MVC Exception Handling using @ExceptionHandler with AngularJS GUI
    Good exception handling is a essential part of any well developed Application Framework and Spring MVC is no exception — pardon the pun. Spring MVC provides several different ways to handle exceptions in our applications. In this tutorial, we will cover Controller Based Exception Handling using the @ExceptionHandler annotation above the method that will handle it.
  • Spring RESTful Web Service Example with JSON and Jackson using Spring Tool Suite
    For this example, I will be using Spring Tool Suite (STS) as it is the best integrated development environment for building the Spring framework projects. Spring is today's leading framework for building Java, Enterprise Edition (Java EE) applications. One additional feature that makes Spring MVC so appealing is that it now also supports REST (REpresentational State Transfer) for build Web Services.
  • Spring MVC RESTful Web Service Example with Spring Data for MongoDB and ExtJS GUI
    This post will show another example of how to build a RESTful web service using Spring MVC 4.0.6, Spring Data for MongoDB 1.6.1 so that we can integrate the web application with a highly efficient datastore (MongoDB 2.6). In this tutorial we will walk you through building the web service and NoSQL database backend and show you how to implement CRUD (Create, Read, Update and Delete) operations.
  • Building DHTMLX Grid Panel User Interface with Spring MVC Rest and MongoDB Backend
    In this tutorial we will show how easy it is to use DHTMLX dhtmlxGrid component while loading JSON data with Ajax pulling in data from the Spring MVC REST web service from our MongoDB data source. You will see how simple it is to create a visually appealing experience for your client(s) with minimal javascript coding.
  • Spring MVC with JNDI Datasource for DB2 on AS/400 using Tomcat
    In this tutorial we will discuss how to set up Spring MVC web services and configure a JNDI Datasource using Tomcat and connect to IBM DB2 Database on a AS/400. JNDI (Java Naming and Directory Interface) provides and interface to multiple naming and directory services.
  • Java Spring MVC Email Example using Apache Velocity
    In this tutorial we will discuss how to set up a Java Spring MVC RESTful Webservice with Email using Apache Velocity to create a Velocity template that is used to create an HTML email message and embed an image, as shown below, using MIME Multipart Message.
  • Implementing Basic and Advanced Search using Angular Material Design, Grid-UI, Spring MVC REST API and MongoDB Example
    In this tutorial we will discuss how to implement basic and advanced search techniques in MongoDB using AngularJS and Google’s Material Design with Spring MVC REST API backend. The advanced search user interface (UI) will use logical operators and build a JSON object which contains the search field name, boolean or logical operator and the search value.
  • Spring MVC Interceptor using HandlerInterceptorAdapter Example
    In this tutorial we will discuss how to use the HandlerInterceptorAdapter abstract class to create a Spring MVC interceptor. These interceptors are used to apply some type of processing to the requests either before, after or after the complete request has finished executing.

Please Share Us on Social Media

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Leave a Reply

Your email address will not be published. Required fields are marked *