Software
Software

Reputation: 351

How do I capture all exceptions of Spring/Spring Boot 2.x?

I built my Spring boot 2.x application using this demo:

https://spring.io/guides/gs/spring-boot/

The problem I'm having is that when there's an exception in Spring/Spring boot, it is printed to standard output. I don't want that. I want to capture them and do other processing such as logging them. I can capture the exceptions of my code but I can't capture the exceptions of Spring/Spring boot. Therefore, how do I capture all exceptions of Spring/Spring Boot 2.x so I can handle them? Is there an easy way to do this, like a generic exception catcher? Can someone show me some code?

My Code:

1. Example.java

   package example;

   import org.springframework.boot.SpringApplication;
   import org.springframework.boot.autoconfigure.SpringBootApplication;
   import org.springframework.boot.builder.SpringApplicationBuilder;
   import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;


   @SpringBootApplication
   public class Example extends SpringBootServletInitializer {

     public static void main(String[] args) throws Exception {

       SpringApplication.run(Example.class, args);
      
     }
  
   }

2. ExampleController.java

   package example;


   import org.springframework.stereotype.Controller;
   import org.springframework.http.HttpStatus;
   import org.springframework.ui.Model;
   import org.springframework.ui.ModelMap;
   import org.springframework.validation.BindingResult;

   import org.springframework.web.bind.annotation.GetMapping;
   import org.springframework.web.bind.annotation.PostMapping;
   import org.springframework.web.bind.annotation.RequestBody;
   import org.springframework.web.bind.annotation.RequestParam;
   import org.springframework.web.bind.annotation.ResponseStatus;
   import org.springframework.web.bind.annotation.ResponseBody;
   import org.springframework.web.bind.annotation.CrossOrigin;

   import org.springframework.web.bind.annotation.ModelAttribute;
   import org.springframework.web.servlet.ModelAndView;


   @Controller
   public class ExampleController {
  

     @GetMapping ("/example")
     public ModelAndView example()
     {
        MyData data= new MyData();
        data.setName("Example");
        data.setVersion("1.0");
    
        ModelAndView model = new ModelAndView("page");
        model.addObject("page", data);
     
       return model;
     }
            
   }

3. GeneralExceptionHandler.java

   package example;

   import org.springframework.web.bind.annotation.ControllerAdvice;
   import org.springframework.web.bind.annotation.ExceptionHandler;

   @ControllerAdvice
   class GeneralExceptionHandler {

    @ExceptionHandler(Exception.class)
    public void handleException() {
      
      System.out.println("Exception handler");
      
    }
   }

4. MyData.java

   package example;

   import lombok.Data;

   @Data
   public class MyData {
  
     private String name;
     private String version;
   }

5. page.jsp

  <!DOCTYPE html>
  <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

  <html> 

   <form:form id="myForm" class="form-horizontal" 
    modelAttribute="page">
    <form:label id="name" class="control-label" path="name" for="name">
    ${page.name}</form:label>
    <!-- Error introduced on purpose to force exception. "version123" should be just "version" -->
    <form:label id="version" class="control-label" path="version" for="version">
    ${page.version123}</form:label>
   </form:form>
      
  </html>

Upvotes: 3

Views: 13193

Answers (2)

Victor1125
Victor1125

Reputation: 692

You can use AOP with pointcut on all public method in Controller. I use BaseController as base class for all my Controllers.

@RestController
@RequestMapping(value = "/api/application")
public class ApllicationController extends ApiController {
   //class body with method
}

Then add AOP handling all exceptions throw from public methods in Controller.

@Aspect
@Configuration
public class AOP_ApiController {

    @Pointcut("execution (public * *(..))")
    private void anyPublicMethod() {}

    @Pointcut("execution (* api.ApiController+.*(..))")//here package and class name as base class
    private void methodOfApiController() {}


    @AfterThrowing(value="methodOfApiController() && anyPublicMethod()", throwing="exception")
    public void afterThrowingExceptionFromApiController(JoinPoint joinPoint, Exception exception) throws Exception {
        ApiController controller = getController(joinPoint);
        String methodName=getMethodName(joinPoint);
        logException(exception, controller, methodName);
        throw exception;
    }

    private ApiController getController(JoinPoint joinPoint) {
        return (ApiController) joinPoint.getTarget();
    }

    private String getMethodName(JoinPoint joinPoint) {
        return joinPoint.getSignature().getName();
    }

    private void logException(Exception ufeException, ApiController controller, String methodName) {
        //log exception as you want
    }
}

Upvotes: 1

Abdelghani Roussi
Abdelghani Roussi

Reputation: 2817

You can use @ExceptionHandler annotation to catch a specific Exception, to do that you can simply annotate a method inside your controller with @ExceptionHandler and provide it with a specific exception, example :

@ExceptionHandler(DataIntegrityViolationException.class)
public void handleException(){
 // do some thing here
}

The limite of this way of doing is that it will handle only exceptions thrown by the @RequestMapping where the @ExceptionHandler is declared. To avoid this limitation you can use a Controller advice which allows you to use exactly the same exception handling techniques but apply them across the whole application, example using controller advice:

@ControllerAdvice
class GeneralExceptionHandler {

    @ExceptionHandler(DataIntegrityViolationException.class)
    public void handleException() {
        // Do some thing here
    }
}

hint : if you want to catch all checked exceptions you can use @ExceptionHandler(Exception.class)

Upvotes: 4

Related Questions