@ControllerAdvice Improvements in Spring 4.0

In my earlier article I have explained about the usage of @ControllerAdvice which is introduced from the Spring 3.2 release. It is special type of @Component to declare the global exceptions handler. When you create a class with @ControllerAdvice and then write few methods with the @ExceptionHandler annotations, any exception thrown in the application will be handled by this class. It is acting as the global exception handler. However, you can not restrict this handling to any specific type of controller or classes.

With the release of Spring 4.0, one of the feature is improvements over the existing @ControllerAdvice annotation. You can narrow the scope of the exception handler. For example, you can declare a exception handler which will handle only the exception thrown by the @RestController , a special type of controller introduced in the Spring 4.0.

Setup Spring 4.0 Environment

Here I am using the same example which I have used for the @ControllerAdvice. If you compare both the posts, you would notice the difference in this tutorial.

1. Create Common Controller

package javabeat.net.exception;

import java.sql.SQLException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class ExceptionHandlingCommonController {

	@RequestMapping(value = "/sqlexceptionexample")
	@ResponseBody
	public String getResultSql() throws SQLException {
		boolean flag = true;
		if (flag) {
			throw new SQLException();
		}
		return "view";
	}

}

2. Create RestConroller

package javabeat.net.exception;

import java.io.IOException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ExceptionHandlingRestController {

	@RequestMapping(value = "/exceptionexample")
	public String getResult() throws IOException {
		boolean flag = true;
		System.out.println("Inside Exception");
		if (flag) {
			throw new IOException();
		}
		return "view";
	}
}

3. @ControllerAdvice for RestController

If you look at the below code, this exception handler called only when the exception is thrown from the RestController.

package javabeat.net.exception;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

@ControllerAdvice(annotations=RestController.class)
public class ExceptionControllerAdvice {
	@ExceptionHandler(Exception.class)
	public ResponseEntity<String> getSQLError(Exception exception){
		HttpHeaders headers = new HttpHeaders();
		headers.set("HeaderKey","HeaderDetails");
		return new ResponseEntity<String>("Rest Controller Advice Example",headers,HttpStatus.ACCEPTED);
	}
}

4. Spring Configuration File

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

http://www.springframework.org/schema/beans/spring-beans-4.0.xsd


http://www.springframework.org/schema/mvc


http://www.springframework.org/schema/mvc/spring-mvc.xsd


http://www.springframework.org/schema/context


http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<context:component-scan base-package="javabeat.net.exception" />

	<mvc:annotation-driven content-negotiation-manager="contentManager"/>
	<bean id="contentManager"
                class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
                <property name="favorPathExtension" value="true"/>
                <property name="ignoreAcceptHeader" value="true" />
                <property name="defaultContentType" value="text/html" />
                <property name="useJaf" value="false"/>
                <property name="mediaTypes">
	                <map>
	                    <entry key="json" value="application/json" />
	                    <entry key="html" value="text/html" />
	                    <entry key="xml" value="application/xml" />
	                </map>
                </property>
        </bean>
	<bean id="jspViewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/jsp/" />
		<property name="suffix" value=".jsp" />
	</bean>

</beans>

If you have any issues while running this example, please post it in the comments section.

Comments

comments

About Krishna Srinivasan

He is Founder and Chief Editor of JavaBeat. He has more than 8+ years of experience on developing Web applications. He writes about Spring, DOJO, JSF, Hibernate and many other emerging technologies in this blog.

Speak Your Mind

*