user2917629
user2917629

Reputation: 942

Java: use of org.springframework.retry.annotation.Retryable

I'm attempting to use org.springframework.retry.annotation.Retryable with an expectation that if a connection reset or timeout happens, the execution can re-try the call again. But so far I'm not getting the retry setup to work properly. The timeout error looks like this this error:

    javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: 
    java.net.SocketTimeoutException: Read timed out

Here is what I have for the retry:

import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

import java.util.function.Supplier;

@Service
public interface RetryService {

    @Retryable(maxAttempts = 4,
            backoff = @Backoff(delay = 1000))
    <T> T run(Supplier<T> supplier);

}

and retry implementing class:

import com.service.RetryService;
import org.springframework.stereotype.Service;

import java.util.function.Supplier;

@Service
public class RetryImpl implements RetryService {
    @Override
    public <T> T run(Supplier<T> supplier) {
        return supplier.get();
    }
}

I use it in the following way:

retryService.run(()->
        myClient.cancel(String id)
);

and MyClient.java has the following implementation for the cancel call and caching:

public Response cancel(String id) {
    String externalUrl = "https://other.external.service/rest/cancel?id="+id;

    WebTarget target = myClient.target(externalUrl);
    return target.request()
                .accept(MediaType.APPLICATION_JSON)
                .cacheControl(cacheControl())
                .buildPut(null)
                .invoke();
}

private static CacheControl cacheControl(){
    CacheControl cacheControl = new CacheControl();
    cacheControl.setMustRevalidate(true);
    cacheControl.setNoStore(true);
    cacheControl.setMaxAge(0);
    cacheControl.setNoCache(true);
    return cacheControl;
}

The externalUrl var above is an endpoint that's a void method - it returns nothing. My hope is that when timeout happens, the retry implementation would fire up and call the external service another time. My setup works in Postman as long as timeout does NOT occur. But if I let it sit for about 30 min, and try again, then I get the timeout error as above. And if I issue another call via Postman right after the timeout, i do get a successful execution. So the retry setup is not working, seems like something falls asleep. I've tried a dazzling number of variations to make it work, but no luck so far. When timeout happens, i see no logs in Kibana in the external service, while getting the the error above on my end. I'm hoping there is something obvious that I'm not seeing here, or maybe there is a better way to do this. Any help is very much appreciated.

Upvotes: 1

Views: 697

Answers (1)

Gary Russell
Gary Russell

Reputation: 174829

You need to set @EnableRetry on one of your @Configuration classes.

See the README: https://github.com/spring-projects/spring-retry

Upvotes: 2

Related Questions