-1

Im trying to implement the Resilience logic inside an aspect class similar to how it has been done for logging. Below is a snippet of code that I have been trying but it doesnt work.

  @Pointcut("within(com.example.demo.*)")
   public void myPointCut() {

  }
  @Around("myPointCut()")
  public String addfaultToleranceRateLimiter(ProceedingJoinPoint pj) throws 
  Throwable,IllegalAccessException,InvocationTargetException {
     String result = applyRLtolerance(pj);
     return result;
  }
  @RateLimiter(name="service1",fallbackMethod = "fallbackRL")
  private String applyRLtolerance(ProceedingJoinPoint pj) throws Throwable {
    String result = (String) pj.proceed();
    return result;
  }

 public String fallbackRL(Throwable t) {
        System.out.println("in fallback" + new Date());
        return "bye";
      }

When pj.proceed() is called the actual logic is executed but the @ratelimiter annotation does not seem to be working as the number of calls getting excuted is not getting limited as per the config given in the application.yml file.

tritpi
  • 11
  • 2
  • Is RateLimiter a custom annotation ? – R.G Jun 14 '20 at 17:17
  • Not the downvoter.The approach attempted appears to be incorrect. Please go through the [documentation](https://resilience4j.readme.io/docs/getting-started-3#annotations) to understand the correct usage. Do note that `resilience4j` itself is AOP based. – R.G Jun 15 '20 at 02:17
  • RateLimiter is an annotation built as part of the Resilience4j library. Im trying to build a wrapper on top of the Resileince4j library such that the client importing the wrapper doesnt have to worry about the complexity of the Resilience4j library. That is the reason Im trying to build an aspect and then call the Resilience annotations in that so that the client doesnt have to do it on their own. Similar to how it is implemented for logging. This will help the client code and Resilience code to be separate. – tritpi Jun 15 '20 at 04:52
  • Could you please update the question with the project pom.xml ? – R.G Jun 15 '20 at 07:18
  • Also , I realized that it is me who downvoted this question and it was not deliberate . I tried to revert the same and cannot do that until the question gets edited again. I wish to revert my mistake if you can help. – R.G Jun 17 '20 at 02:23

2 Answers2

0

Most of the annotations are handled using AOP if you call an annotated method in the same class than annotation won't be in effect. AOP also has a problem with the order when more than one aspect is satisfying the execution criteria.

In your case, you are calling the method from the same class so annotation is not in effect. You can solve this by moving the rate limiter related methods to another class.

class MyAspect{
   RateLimiterSercvice rls = new RateLimiterSercvice();
   @Pointcut("within(com.example.demo.*)")
   public void myPointCut() {

   }
   @Around("myPointCut()")
   public String addfaultToleranceRateLimiter(ProceedingJoinPoint pj) throws 
    Throwable,IllegalAccessException,InvocationTargetException {
     String result = rls.applyRLtolerance(pj);
     return result;
  }
}


class RateLimiterService {
  @RateLimiter(name="service1",fallbackMethod = "fallbackRL")
  public String applyRLtolerance(ProceedingJoinPoint pj) throws Throwable {
    String result = (String) pj.proceed();
    return result;
  }
  public String fallbackRL(Throwable t) {
        System.out.println("in fallback" + new Date());
        return "bye";
  }
}




sonus21
  • 5,178
  • 2
  • 23
  • 48
  • I tried this by moving the rateLimiter related methods to a different class. It didnt work. – tritpi Jun 14 '20 at 13:24
0

You will need to configure the wrapper class as a spring bean and autowire the same in the Aspect.

The code did not work for the following reasons.

  1. When an instance is created with new keyword , it is not a spring managed bean.
  2. Spring AOP cannot intercept/advice an internal method call.

Following code works

@Aspect
@Component
public class ResilienceAspect {

    @Autowired
    ResilienceWrapper wrapper;

    @Pointcut("within(com.example.demo.*)")
    public void myPointCut() {

    }

    @Around("myPointCut()")
    public String addfaultToleranceRateLimiter(ProceedingJoinPoint pj)
            throws Throwable, IllegalAccessException, InvocationTargetException {
        String result = wrapper.applyRLtolerance(pj);
        return result;
    }
}

Wrapper

@Component
public class ResilienceWrapper {

    @RateLimiter(name = "service1", fallbackMethod = "fallbackRL")
    public String applyRLtolerance(ProceedingJoinPoint pj) throws Throwable {
        String result = (String) pj.proceed();
        return result;
    }

    public String fallbackRL(Throwable t) {
        System.out.println("in fallback" + new Date());
        return "bye";
    }
}

Please note :

within(com.example.demo.*) may be tuned so that it will not interfere with the Aspect code. If the ResilienceAspect is also within com.example.demo , the run would have undesired results.

Hope this helps.

R.G
  • 6,436
  • 3
  • 19
  • 28