Search code examples
javaspringaopaspectjspring-aop

Spring AOP @Before advice return value


I'm new with Spring AOP and I was wondering if it is possible to return a value from @Before to method and use this variable inside it, for example:

@Before("@annotation(CheckUserReservationPermission) && args(username,idReservation)")
public Reservation userCreationAdvice(ProceedingJoinPoint pjp, String username, Integer idReservation) throws Throwable {
    Reservation reservation = reservationServices.findById(idReservation);
    if (!reservation.getUser().getUsername().equals(username))
        throw new PermissionException("You can't delete the reservation with id: " + idReservation);
    return reservation;
}

and my method:

@Override
@CheckUserReservationPermission
public void deleteReservationById(String username, Integer idReservation) throws QueryException {
    synchronized(ReservationsSchedulerServicesImpl.class){
        databaseReservationServices.deleteReservationById(username, reservation);  
    }
}

Is there a way to make this? Otherwise I have to repeat the query. Thanks

UPDATE: With @Around I may have this code, but how can I retrieve the variable into deleteReservationById method?

@Around("@annotation(CheckUserReservationPermission) && args(username,idReservation)")
public Object userCreationAdvice(ProceedingJoinPoint pjp, String username, Integer idReservation) throws Throwable {
    Reservation reservation = reservationServices.findById(idReservation);
    if (!reservation.getUser().getUsername().equals(username))
        throw new PermissionException("You can't delete the reservation with id: " + idReservation);
    return pjp.proceed(new Object[] {reservation});
}

Solution

  • Edit 2:

    1. Advice

      @Around("@annotation(CheckUserReservationPermission) && args(username,idReservation)")
      public Object userCreationAdvice(ProceedingJoinPoint pjp, DeleteByIdRequest req) throws Throwable {
          Reservation reservation = reservationServices.findById(idReservation);
          if (!reservation.getUser().getUsername().equals(username)) {
              throw new PermissionException("You can't delete the reservation with id: " + idReservation);}
      
           req.setReservation(reservation);  
          return pjp.proceed(new Object[] {req});
      

      }

    2. New Request POJO

     class DeleteByIdRequest {
          Reservation reservation;
          String username;
          Integer idReservation;
        }
    

    3.Target Method

    @Override
    @CheckUserReservationPermission
    public void deleteReservationById(DeleteByIdRequest request) throws QueryException {
        synchronized(ReservationsSchedulerServicesImpl.class){
            databaseReservationServices.deleteReservationById(username, reservation);  
        }
    }
    

    See the interfaces of this advices,

    check what they return.

    1.ThrowsAdvice

    public void afterThrowing(IllegalArgumentException e) throws Throwable {
    }
    

    2.AfterReturningAdvice

    public void afterReturning(Object returnValue, Method method,
            Object[] args, Object target) throws Throwable {
    }
    

    3.MethodBeforeAdvice

    public void before(Method method, Object[] args, Object target)
            throws Throwable {
    
    }
    

    4.MethodInterceptor (Around Advice)

    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
    
    }
    

    If you note in 4th point only Around advice is returning object.

    you have to define the joinPoint.proceed() to control when should the interceptor return the control to the original method.

    Check simple example here

    EDIT: I think this can be achieved with help of proceeding with arguments
    Basically you can then call proceed() with the new arguments.