Search code examples
javaspringasynchronousrate-limitingaspect

Validation exceptions in Aspect are swallowed in case of @Async annotation


I have a method defined as:

  @Async("queryTaskExecutor")
    @RateLimitation(rateSize = 10)
    public Future<RunQueryCommandResult> execute(final Path xmlPath,
                                                 final Boolean calculateAlreadyAllowedTraffic,
                                                 final String sessionId,
                                                 final boolean isQueryFromAFA,
                                                 final String mode) {}

RateLimitation is a custom annotation for RateLimiter validation for each method excecution. the annoration triggering an Aspect which defined as:

@Aspect
public class RateLimitationAspect {
    private static final Logger log = LoggerFactory.getLogger(RateLimitationAspect.class);
    @Autowired
    RateLimitationValidator rateLimitationValidator;

    public RateLimitationAspect() {
    }

    @Before("@annotation(rateLimitation)")
    public void aroundRateLimitationAction(JoinPoint joinPoint, RateLimitation rateLimitation) throws Throwable {
        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        log.info("Validating rate limitation on method " + method.getName());
        if (!this.rateLimitationValidator.isValid(method, (ConstraintValidatorContext)null)) {
            throw new IllegalStateException(MessageFormat.format("Calling method [{0}] reached the maximum permitted calls per second, request is denied.", method.toString()));
        }
    }
}

I have created a test for checking the rate validation:

 @Test(expected = IllegalStateException.class)
    public void test_execute_command_service_in_forbidden_amount_parallel()  {

        IntStream.range(1, 40).parallel().forEach(i ->
                runQueryCommandService.execute(XML_PATH, false, VALID_ALL_FIREWALLS_SESSION, false, QUERY)
        );
    }

The test is failing because the IllegalStateException is not thrown. When I am debugging the test the IllegalStateException is indeed been thrown in the Aspect code due to validation error.

The llegalStateException is swallowed. If I remove the @Async annotation from the method definition the test is working. Please help.


Solution

  • The problem was that calling the method with the @Async annotation won't trigger the Spring bean proxy. I solved it by changing the test to call the controller ( the one that calls the tested service). And then the exception is thrown and catched as expected.