'Returning proper value from @AfterThrowing

I am new to String, SpringBoot. Can we suppress thrown exception in a method annotated with @AfterThrowing? I mean when an exception is thrown, it will suppress that and will return a default value on behalf of the invoking method? Say, I have a controller -

@RestController
public class MyRestController implements IRestController{

    @Override
    @GetMapping("hello-throw")
    public String mustThrowException(@RequestParam(value = "name")final String name) throws RuntimeException {

        System.out.println("---> mustThrowException");
        if("Bakasur".equals(name)) {
            throw new RuntimeException("You are not welcome here!");
        }
        return name + " : Welcome to the club!!!";
    }
}

I have created a @AspectJ, as follows -

@Aspect
@Component
public class MyAspect {

    @Pointcut("execution(* com.crsardar.handson.java.springboot.controller.IRestController.*(..))")
    public void executionPointcut(){

    }

    @AfterThrowing(pointcut="executionPointcut()",
            throwing="th")
    public String afterThrowing(JoinPoint joinPoint, Throwable th){

        System.out.println("\n\n\tMyAspect : afterThrowing \n\n");

        return "Exception handeled on behalf of you!";
    }
}

If I run this & hit a ULR like - http://localhost:8080/hello-throw?name=Bakasur I will get RuntimeException, but, I want to return a default message like - Exception handeled on behalf of you!, can we do it using @AfterThrowing?

I know it can be done using @Around, but around will be called on every hit of the url, that I do not want



Solution 1:[1]

What you want to do is Exception Handling on the controller. You don't need to build it yourself, Spring already supports you with some annotations like @ExceptionHandler and @ControllerAdvice. Best would be to follow this example: https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc#using-controlleradvice-classes

@ControllerAdvice
class GlobalControllerExceptionHandler {

    @ResponseStatus(HttpStatus.CONFLICT)  // 409
    @ExceptionHandler(DataIntegrityViolationException.class)
    public void handleConflict() {
        // Nothing to do
    }
}

@ControllerAdvice
class GlobalDefaultExceptionHandler {
  public static final String DEFAULT_ERROR_VIEW = "error";

  @ExceptionHandler(value = Exception.class)
  public ModelAndView
  defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
    // If the exception is annotated with @ResponseStatus rethrow it and let
    // the framework handle it - like the OrderNotFoundException example
    // at the start of this post.
    // AnnotationUtils is a Spring Framework utility class.
    if (AnnotationUtils.findAnnotation
                (e.getClass(), ResponseStatus.class) != null)
      throw e;

    // Otherwise setup and send the user to a default error-view.
    ModelAndView mav = new ModelAndView();
    mav.addObject("exception", e);
    mav.addObject("url", req.getRequestURL());
    mav.setViewName(DEFAULT_ERROR_VIEW);
    return mav;
  }

}

Solution 2:[2]

You should use the fully qualified name of the class before method's name when you're referring to a pointcut. So, you should change @AfterThrowing something like this.

@AfterThrowing(pointcut="packageName.MyAspect.executionPointcut()",
            throwing="th")

Please note that packageName is full package name of MyAspect.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Ahmadreza Sedighi