6

I have following method which is @Retryable:

    @Retryable(value = HttpClientErrorException.class)
    public Integer callToExternalService(DateTime start, DateTime end) throws MyException

My question is if I can modify input parameters each time method is under retry because I need to make a rest call with different values. Is there an option similar to @Recover for this case?

Clawdidr
  • 577
  • 1
  • 8
  • 25

1 Answers1

2

Not out of the box; you would need to add another advice closer to the bean than the retry interceptor to modify the MethodInvocation.arguments.

Or you could subclass the retry interceptor and override the invoke method.

Neither one is trivial, unless you have some knowledge about Spring proxies.

Here's a simpler way to do it; it will need a bit more work if you need to recover rather than throw the last exception to the caller.

@SpringBootApplication
@EnableRetry
public class So61486701Application {

    public static void main(String[] args) {
        SpringApplication.run(So61486701Application.class, args);
    }

    @Bean
    MethodInterceptor argumentChanger() {
        RetryTemplate retryTemplate = new RetryTemplate();
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(3);
        FixedBackOffPolicy backOff = new FixedBackOffPolicy();
        backOff.setBackOffPeriod(1000L);
        retryTemplate.setRetryPolicy(retryPolicy);
        retryTemplate.setBackOffPolicy(backOff);
        return invocation -> {
            return retryTemplate.execute(context -> {
                if (context.getRetryCount() > 0) {
                    Object[] args = invocation.getArguments();
                    args[0] = ((Integer) args[0]) + 1;
                    args[1] = ((String) args[1]) + ((String) args[1]);
                }
                return invocation.proceed();
            });
        };
    }


    @Bean
    public ApplicationRunner runner(Foo foo) {
        return args -> foo.test(1, "foo.");
    }

}

@Component
class Foo {

     @Retryable(interceptor = "argumentChanger")
     public void test(int val, String str) {
        System.out.println(val + ":" + str);
        throw new RuntimeException();
     }

 }
Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • So, if I want to change value each time I try to call the rest service, would it be better to just use a ```while``` or ```for``` loop instead? – Clawdidr Apr 28 '20 at 18:24
  • I can't really answer that, but it's probably much less work. – Gary Russell Apr 28 '20 at 18:34
  • Do you know about any documentation regarding the two options you mentions above in the answer? As you said, neither look trivial. – Clawdidr Apr 28 '20 at 19:03