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.
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.