Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why a Spring Around advice can swallow, or halt the propagation of, an exception thown by the target method?

I am studying for the Spring Core certification and I have the following doubt on this question founded on my study material:

Which of the following statments is NOT true about advice types and exception handling?

  • If a Before advice throws an exception, the target method will not be called.

  • An Around advice can swallow, or halt the propagation of, an exception thown by the target method.

  • An AfterReturning advice type can swallow, or halt the propagation of, an exception thown by the target method.

Now I know that the correct answer of the previous question is the last one (I have the answers) but why?

So it ask me what statment is not true so it means that the first 2 statments are true.

I am trying to analyze the previous 3 case doing some concrete example but I am not soure that my reasoning are correct.

1) BEFORE ADVICE:

I can have something like this:

@Aspect
public class PropertyChangeTracker {
    private Logger logger = Logger.getLogger(getClass());

    @Before(“execution(void check*(*))”)
    public void trackCheck() {
        logger.info(“Property about to check…”);
   }
}

So the implemented advice (that create a log row into a .log file) is performed each time that a checkSomething(oneArgument) method is performed. If during the execution of this method an exception is thrown the advice is not performed.

I think that this is pretty clear

2) AROUND ADVICE, I know that this is the sequence diagram of the Around advice

enter image description here

and I have the following example of this kind of advice:

@Around("execution(* com.journaldev.spring.model.Employee.getName())")
public Object employeeAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
    System.out.println("Before invoking getName() method");
    Object value = null;
    try {
        value = proceedingJoinPoint.proceed();
    } catch (Throwable e) {
        e.printStackTrace();
    }
    System.out.println("After invoking getName() method. Return value="+value);
    return value;
}

Reading the official documentation I found that:

Around advice: Advice that surrounds a join point such as a method invocation. This is the most powerful kind of advice. Around advice can perform custom behavior before and after the method invocation. It is also responsible for choosing whether to proceed to the join point or to shortcut the advised method execution by returning its own return value or throwing an exception.

So it seems to me that Around advice is used to cut the method execution before and after the jointpoint execution. We can use it to control whether the advised method will execute or not. We can also inspect the returned value and change it. This is the most powerful advice and needs to be applied properly.

So in the previous example I think that it is performed twice time: the first one before that the getName() method is executed and a second one after that the getName() method is executed.

But what exacty does the

value = proceedingJoinPoint.proceed();

I think that it is the division point between the execution before and after the joint point, in this case I think that the proceed() method say that the getName() method have to be performed and that its result is to be putted into the value field. Is it right or am I missing something?

So coming back to the original statment I can say that

An Around advice can swallow, or halt the propagation of, an exception thown by the target method.

why can I say that this is true? What exatly means?

like image 878
AndreaNobili Avatar asked Apr 13 '15 14:04

AndreaNobili


2 Answers

So in the previous example I think that it is performed twice time: the first one before that the getName() method is executed and a second one after that the getName() method is executed.

If I understood what you think here, you are wrong. The advice is called only once, and the code in it is responsible for calling the actual advised method getName(). That's what proceedingJoinPoint.proceed() does.

One typical scenario - you intercept the method call, perform some checks, invoke the method (or not, maybe depending on the result of the checks), and return the result. In the example you posted, proceed() is surrounded with try - catch block, which means you can catch the exception thrown by the getName() and do whatever you want with it. This explains why the second sentence in your question is true.

like image 113
Predrag Maric Avatar answered Sep 28 '22 16:09

Predrag Maric


Using @Around is just like writing your own code and calling a method, except that you use proceedingJoinPoint.proceed() instead. As with a normal method call, you can choose to not execute it (wrap it in a conditional) or catch errors thrown by it (wrap the call in a try block).

From the spring documentation:

Around advice is declared using the @Around annotation. The first parameter of the advice method must be of type ProceedingJoinPoint. Within the body of the advice, calling proceed() on the ProceedingJoinPoint causes the underlying method to execute. The proceed method may also be called passing in an Object[] - the values in the array will be used as the arguments to the method execution when it proceeds.

So, specifically: value = proceedingJoinPoint.proceed(); causes the underlying method to be called and its return value to be assigned to value.

An Around advice can swallow, or halt the propagation of, an exception thown by the target method.

This happens by doing:

try {
   proceedingJoinPoint.proceed();
} catch (Throwable e) {
    // ignore or handle
}
like image 40
beerbajay Avatar answered Sep 28 '22 16:09

beerbajay