I have the spring mvc application. To catch exceptions I use @ExceptionHandler
annotation.
@ControllerAdvise
public class ExceptionHandlerController {
@ExceptionHandler(CustomGenericException.class)
public ModelAndView handleCustomException(CustomGenericException ex) {
....
}
}
But I think that I will catch only exceptions after controller methods invocations.
But how to catch exceptions generated outside the rest context? For example lifecycle callbacks or scheduled tasks.
Another way to handle controller level exceptions is by overriding the OnException() method in the controller class. This method handles all your unhandled errors with error code 500. It allows you to log an exception and redirect to the specific view. It does not require to enable the <customErrors> config in web.
Spring MVC Framework provides following ways to help us achieving robust exception handling. Controller Based - We can define exception handler methods in our controller classes. All we need is to annotate these methods with @ExceptionHandler annotation. This annotation takes Exception class as argument.
Spring security exceptions can be directly handled by adding custom filters and constructing the response body. To handle these exceptions at a global level via @ExceptionHandler and @ControllerAdvice, we need a custom implementation of AuthenticationEntryPoint.
Spring MVC provides exception handling for your web application to make sure you are sending your own exception page instead of the server-generated exception to the user. The @ExceptionHandler annotation is used to detect certain runtime exceptions and send responses according to the exception.
But how to catch exceptions generated outside the rest context? For example lifecycle callbacks or scheduled tasks
One solution that I can think of it, is to use a After Throwing Advice. The basic idea is to define an advice that would caught exceptions thrown by some beans and handle them appropriately.
For example, you could define a custom annotation like:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Handled {}
And use that annotation to mark methods that should be advised. Then you can annotate your, say, jobs with this annotation:
@Component
public class SomeJob {
@Handled
@Scheduled(fixedRate = 5000)
public void doSomething() {
if (Math.random() < 0.5)
throw new RuntimeException();
System.out.println("I escaped!");
}
}
And finally define an advice that handles exceptions thrown by methods annotated with @Handled
:
@Aspect
@Component
public class ExceptionHandlerAspect {
@Pointcut("@annotation(com.so.Handled)")
public void handledMethods() {}
@AfterThrowing(pointcut = "handledMethods()", throwing = "ex")
public void handleTheException(Exception ex) {
// Do something useful
ex.printStackTrace();
}
}
For more finer grain control over method executions, you could use Around Advice, too. Also don't forget to enable autoproxy-ing, using @EnableAspectJAutoProxy
on a Java config or <aop:aspectj-autoproxy/>
in XML configurations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With