SpringRetry etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
SpringRetry etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

16 Haziran 2023 Cuma

SpringRetry RetryListenerSupport Sınıfı

Giriş
Şu satırı dahil ederiz
import org.springframework.retry.listener.RetryListenerSupport;
Kullanım
Örnek
Şöyle yaparız
@Bean public RetryTemplate installTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); retryTemplate.registerListener(new MyRetryListener()); return retryTemplate; }
Örnek
Şöyle yaparız
public class MyRetryListener extends RetryListenerSupport {

  @Override
  public <T, E extends Throwable> void onError(RetryContext context, 
                                               RetryCallback<T, E> callback, 
                                               Throwable throwable) {
    Metrics.addMetric("mysql_connection_error",1);
    super.onError(context,callback,throwable);
  }
  ...
}

6 Mart 2023 Pazartesi

SpringRetry UniformRandomBackOffPolicy Sınıfı

Örnek
Şöyle yaparız
import org.springframework.retry.RetryPolicy;
import org.springframework.retry.backoff.BackOffPolicy;
import org.springframework.retry.backoff.UniformRandomBackOffPolicy;
import org.springframework.retry.support.RetryTemplate;

public class PayApiRetryTemplate extends RetryTemplate implements InitializingBean {

  @Override
  public void afterPropertiesSet() throws Exception {
    this.setBackOffPolicy(backOffPolicyWithJitter());
    this.setRetryPolicy(...);
  }

  private BackOffPolicy backOffPolicyWithJitter() {
    UniformRandomBackOffPolicy policy = new UniformRandomBackOffPolicy();
    policy.setMaxBackOffPeriod(this.prop.getRetry().getMaxBackoff());
    policy.setMinBackOffPeriod(this.prop.getRetry().getMinBackoff());
    return policy;
  }
}

26 Temmuz 2021 Pazartesi

SpringRetry FixedBackOffPolicy Sınıfı

Giriş
Açıklaması şöyle.
BackOffPolicy is used to control back off between retry attempts. A FixedBackOffPolicy pauses for a fixed period of time before continuing.
Örnek
Şöyle yaparız
@Bean
public RetryTemplate retryTemplate() {

  RetryTemplate retryTemplate = new RetryTemplate();

  //BackOff Policy
  FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
  fixedBackOffPolicy.setBackOffPeriod(2000l);
  retryTemplate.setBackOffPolicy(fixedBackOffPolicy);

  //Retry Policy
  SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
  retryPolicy.setMaxAttempts(2);
  retryTemplate.setRetryPolicy(retryPolicy);

  return retryTemplate;

}

SpringRetry TimeoutRetryPolicy Sınıfı

Örnek - timeout
Şöyle yaparız
RetryTemplate template = new RetryTemplate();

TimeoutRetryPolicy policy = new TimeoutRetryPolicy();
policy.setTimeout(30000L);

template.setRetryPolicy(policy);

Foo result = template.execute(new RetryCallback<Foo>() {
@Override
    public Foo doWithRetry(RetryContext context) {
        // Do stuff that might fail, e.g. webservice operation
        return result;
    }

});

SpringRetry SimpleRetryPolicy Sınıfı

Giriş
Şu satırı dahil ederiz
import org.springframework.retry.policy.SimpleRetryPolicy;
Açıklaması şöyle.
RetryPolicy determines when an operation should be retried. A SimpleRetryPolicy is used to retry a fixed number of times.
constructor
Örnek
Şöyle yaparız
public class PayApiRetryTemplate extends RetryTemplate implements InitializingBean {

  private final PayApiConnProp prop;
  private final Class<? extends ApiException>[] exceptions;

    @Override
    public void afterPropertiesSet() throws Exception {
        this.setBackOffPolicy(...);
        this.setRetryPolicy(retryPolicy());
    }

   
  private Map<Class<? extends Throwable>, Boolean> includedExceptions() {
    Map<Class<? extends Throwable>, Boolean> includedExceptions = new HashMap<>();
    for (Class<? extends ApiException> exception : this.exceptions) {
      includedExceptions.put(exception, true);
    }
    return includedExceptions;
  }

  private RetryPolicy retryPolicy() {
    return new SimpleRetryPolicy(this.prop.getRetry().getMaxAttempts(), 
      includedExceptions());
  }
}
setMaxAttempts metodu
Örnek
Şöyle yaparız
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;

@SpringBootApplication
@EnableRetry
@EnableJpaRepositories(basePackages = "com.betterjavacode.retrydemo.daos")
public class RetrydemoApplication {

  @Bean
  public RetryTemplate retryTemplate(){
    RetryTemplate retryTemplate = new RetryTemplate();

    FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
    backOffPolicy.setBackOffPeriod(100);

    SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy();
    simpleRetryPolicy.setMaxAttempts(2);

    retryTemplate.setRetryPolicy(simpleRetryPolicy);
    retryTemplate.setBackOffPolicy(backOffPolicy);
    return retryTemplate;
  }
}

12 Ocak 2021 Salı

SpringRetry Kullanımı

Giriş
SpringRetry kütüphanesinin anotasyonları taraması için

1. @EnableRetry anotasyonunu tanımlamak gerekir veya
2. spring.retry.enabled=true tanımını yapmak gerekir.

Maven
Şu satırı dahil ederiz
<dependency>
  <groupId>org.springframework.retry</groupId>
  <artifactId>spring-retry</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
  <version>2.3.1.RELEASE</version>
</dependency>
SpringRetry'ı kullanmak için iki tane yöntem var 
1. Metodun üzerine @Retryable koymak. Bu kolay olan yöntem. @Retryable başarısız olursa @Recover ile belirtilen metod çalıştırılır 
2. RetryTemplate sınıfını kod içinde kullanmak. Bu zor olan yöntem

Örnek
Şöyle yaparız. Burada RestTemplate kullanırken exception alınırsa, tekrar deneniyor.
@EnableRetry
@Configuration
public class CommonConfig {
  @Bean
  public RestTemplate restTemplate() {
   return new RestTemplate();
  }
}

@Slf4j
@Service
public class ExternalService {
  static final String URL = "http://localhost:8081/target/readiness";

  @Autowired
  private RestTemplate restTemplate;

  @Retryable(retryFor = Exception.class, 
             maxAttempts = 10, 
             backoff = @Backoff(delay = 1000))
  public String checkWithRetry() {
    HttpEntity<?> entity = new HttpEntity<Object>(null, null);
    ResponseEntity<String> response = restTemplate.exchange(URL, HttpMethod.GET, 
      entity, String.class);
    return response.getBody();
  }
}
Aynı şeyi kodla yapsaydık şöyle olurdu
public String checkWithRetry() {
  long timeToWait = 1000;
  int numRetry = 1;
  int maxAttempts = 10;
  boolean isDataReady = false;
  String result = null;
  do {
   try {
    HttpEntity<?> entity = new HttpEntity<Object>(null, null);
    ResponseEntity<String> response = restTemplate.exchange(URL, HttpMethod.GET, 
      entity, String.class);
    result = response.getBody();
    isDataReady = true;
   } catch (Exception e) {
    try {
     Thread.sleep(timeToWait);
    } catch (InterruptedException exception) {
      ...
    }
    numRetry++;
   }
  } while (!isDataReady && numRetry <= maxAttempts);
  return result;
 }





14 Ocak 2020 Salı

SpringRetry RetryTemplate Sınıfı

Giriş
Şu satırı dahil ederiz. 
import org.springframework.retry.support.RetryTemplate;
- RetryOperations arayüzünden kalıtır. Bu arayüzün 4 tane overload edilmiş execute() metodu var. Bu metodlar parametre olarak RetryCallback, RecoveryCallback, RetryState nesneler alırlar.
RetryCallback yapılması istenen işi temsil eder.

- Bu sınıfı bir bean yapmak iyi bir fikir olabilir.

Stateless retry interceptor
Açıklaması şöyle. Yani thread'i bloke eder
... all retry attempts happen without exiting the interceptor call, so the interceptor is called only once regardless of the number of retries. Any required state (e.g. number of attempts) is kept on the stack.
Stateful retry interceptor
Açıklaması şöyle. Yani thread'i bloke etmez
Spring Retry also provides a stateful retry interceptor in which case the Exception is propagated outside of the interceptor. In other words the interceptor is called once per retry, therefore it needs to somehow remember the state of the retries (hence it is called stateful). The main use case for a stateful retry interceptor is so that it can be used in Hibernate transactions (through the Spring @Transactional interceptor), where if the Hibernate Session throws an exception, the transaction must be rolled back and the Session discarded. This means that upon failure the call has to exit the retry interceptor, so that the transaction interceptor can close the session and open a new one for each retry attempt.
execute metodu - RetryCallback
RetryCallback exception fırlatırsa backoffpolicy ve retrypolicy müsaade ediyorsa, tekrar çalıştırılır.

RetryCallback sınıfının doWithRetry() metodu RetryContext parametresi alır. Açıklaması şöyle
The method parameter for the RetryCallback is a RetryContext. Many callbacks ignore the context. However, if necessary, you can use it as an attribute bag to store data for the duration of the iteration.

A RetryContext has a parent context if there is a nested retry in progress in the same thread. The parent context is occasionally useful for storing data that needs to be shared between calls to execute.
Örnek - lambda
Şöyle yaparız
retryTemplate.execute(arg -> callMyFunction());
Örnek
Şöyle yaparız.
public Object getSomething(@PathVariable("id") String id) throws Exception{

  return retryTemplate.execute(new RetryCallback<Object, Exception>() {
    @Override
    public Object doWithRetry(RetryContext arg0) {
      Object o = restTutorialClient.getEmployeesList(id);
      return o;
    }
});
Örnek
RetryCallback arayüzü yerine lambda kullanmak için şöyle yaparız.
@Service
public class TestService {

  @Autowired
  private RetryTemplate retryTemplate;

  public String testService() {

    //Retryable
    String result = retryTemplate.execute(context -> {
      System.out.println("Inside the Method, Retry = " + context.getRetryCount());
      if (context.getRetryCount() == 0)
        throw new RuntimeException("Something went wrong");
      return "Successfully Completed";
    });

    //Result
    System.out.println("FINAL Result = " + result);
    return result;
  }
}  
execute metodu - RetryCallback + RecoveryCallback
Örnek
Şöyle yaparız
Foo foo = template.execute(new RetryCallback<Foo>() {
  public Foo doWithRetry(RetryContext context) {
    // business logic here
  },
  new RecoveryCallback<Foo>() {
    Foo recover(RetryContext context) throws Exception {
          // recover logic here
    }
});
registerListener metodu
RetryListenerSupport sınıfı yazısına taşıdım

setBackOffPolicy metodu
FixedBackOffPolicy kullanılabilir.

setPolicyMap metodu
Örnek
Şöyle yaparız.
@Bean(name="myRetryTemplate")
public RetryTemplate retryTemplate() {

  RetryTemplate retryTemplate = new RetryTemplate();
  SimpleRetryPolicy simpleRetryPolicyCheck = new SimpleRetryPolicy();
  simpleRetryPolicyForOkta.setMaxAttempts(3);

  Map<Class<? extends Throwable>, RetryPolicy> policyMap = new HashMap<>();
  policyMap.put(Exception1.class, simpleRetryPolicyCheck );
  policyMap.put(Exception2.class, simpleRetryPolicyCheck );

  ExceptionClassifierRetryPolicy retryPolicy = new ExceptionClassifierRetryPolicy();
  retryPolicy.setPolicyMap(policyMap);
  retryTemplate.setRetryPolicy(retryPolicy);
  return retryTemplate;
}
setRetryPolicy metodu
SimpleRetryPolicy kullanılabilir. Belirtilen sayı kadar tekrar dener
TimeoutRetryPolicy kullanılabilir;