My method requires two API calls, and is decorated with Spring Boot's @Cacheable
as well as Resilience4j's @RateLimiter
(link to doc):
@Cacheable(value = "getProjectFile")
@RateLimiter(name = "getProjectFile")
public Optional<String> getProjectFile(String projectName) {
return getFileName(projectName).flatMap(this::getProjectFileFromFileName);
}
private Optional<String> getFileName(String projectName) {
String url = getUrlFromProjectName(projectName);
return Optional.ofNullable(restTemplate.getForObject(url, String.class));
}
private Optional<String> getProjectFileFromFileName(String fileName) {
String url = getUrlFromFileName(fileName);
return Optional.ofNullable(restTemplate.getForObject(url, String.class));
}
Both annotations work perfectly - but the rate limiter turns on even when accessing cached values, slowing down my programme unnecessarily.
To fix this, I tried moving the @RateLimiter
annotation to getFileName
, getProjectFileFromFileName
, or both - but all of a sudden it stops working (the code compiles, but requests are too frequent).
Why does @RateLimiter
work on the first function, but not the second or third? And how can I get the rate limiter inside the cached function?
Because of Spring AOP annotations don't work when you call a method, which is annotated, locally from the same class (bean), because then the PROXY is bypassed.
@Cacheable
and @RateLimiter
on the same method might not work, because of the Spring AOP Aspect order. See: https://docs.spring.io/spring-framework/docs/4.3.15.RELEASE/spring-framework-reference/html/aop.html#aop-ataspectj-advice-ordering
You can configure the order of the RateLimiter globally, but it might be better to move the method getFileName
into another Bean und only use @RateLimiter
.