Search code examples
javaspring-webfluxproject-reactorspring-aop

Execute custom annotation in webflux application before method execution


How can I avoid using the .block() method in the aspect component while making sure the annotation is completed before the method where is called starts executing?

I have some validations that needs to be executed before some methods from a service are executed

I have created a custom annotation, that I can use to annotate each method where I want to perform the validation

The Annotation looks like this:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PerformValidationInterface{

}

The Aspect method that i want to be executed looks like this:

    @Before("execution(* *.*(..)) && @annotation(performValidation)")
    public Mono<Void> doBeforeMethod(JoinPoint joinPoint, PerformValidationInterface performValidation) {

        return validationService.validateObject(object)
                         //i am using defer becaue I don't want to evaluate the switchIfEmpty()  if the validateObject() returns something 
                         .switchIfEmpty(Mono.defer( 
                              () -> anotherService.checkIfObjectExists(object)))      
                         .block();
}

public ValidationService {

    public Mono<Object> validateObject(Object object) {
            //perform object validation
            if (objectIsValid) { 
                return Mono.just(object) 
            } else { 
                return Mono.empty()
            }
    }

}

public FooService {



     //How can I avoid using the .block() method in the aspect component while making sure the annotation is completed before the barMethod starts executing
      @PerformValidation
      public Mono<Bar> barMethod(Object arg1, Object arg2 ) {
         //do some stuff and return a Mono<Bar>

      }
}

Solution

  • My solution looks like this:

    @Around("execution(* *.*(..)) && @annotation(performValidation)")
    public Mono doBeforeMethod(JoinPoint joinPoint, PerformValidationInterface performValidation) {
      return validationService
        .validateObject(object)
        //i am using defer becaue I don't want to evaluate the switchIfEmpty() if the validateObject() returns something 
        .switchIfEmpty(
          Mono.defer( 
            () -> anotherService.checkIfObjectExists(object)
          )
        )
        .then((Mono) joinPoint.proceed());
    }
    

    .then() -> will wait until your validation logic(or some other logic) is completed, THEN will call the joinPoint.proceed()

    joinPoint.proceed() -> will continue the execution of the annotated method