Skip to content

Instantly share code, notes, and snippets.

@luismendes070
Created April 27, 2025 13:53
Show Gist options
  • Save luismendes070/96f615f5613fa523ec5072af8b2b1fac to your computer and use it in GitHub Desktop.
Save luismendes070/96f615f5613fa523ec5072af8b2b1fac to your computer and use it in GitHub Desktop.
DeepSeek prompt:"Implement java spring boot retry logic"
# Implementing Retry Logic in Spring Boot
Spring Boot provides an easy way to implement retry logic using the Spring Retry module. Here's how to implement it:
## 1. Add Dependencies
First, add the Spring Retry dependency to your `pom.xml` (for Maven):
```xml
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
```
Or for Gradle (`build.gradle`):
```groovy
implementation 'org.springframework.retry:spring-retry'
implementation 'org.springframework:spring-aspects'
```
## 2. Enable Retry
Add `@EnableRetry` to your main application class or any configuration class:
```java
@SpringBootApplication
@EnableRetry
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
```
## 3. Basic Usage with @Retryable
Annotate the method you want to retry with `@Retryable`:
```java
@Service
public class MyService {
@Retryable(value = {RuntimeException.class},
maxAttempts = 3,
backoff = @Backoff(delay = 1000))
public String callExternalService() {
// Code that might fail
return externalService.call();
}
}
```
Parameters:
- `value`: Exception types that should trigger a retry
- `maxAttempts`: Maximum number of attempts (including initial call)
- `backoff`: Delay between attempts (1000ms in this example)
## 4. Adding a Recovery Method
You can specify a fallback method when all retries fail:
```java
@Service
public class MyService {
@Retryable(value = {RuntimeException.class}, maxAttempts = 3)
public String callExternalService() {
// Code that might fail
return externalService.call();
}
@Recover
public String recover(RuntimeException e) {
// Fallback logic
return "Fallback response";
}
}
```
## 5. Custom Retry Template
For more control, you can configure a RetryTemplate:
```java
@Configuration
public class RetryConfig {
@Bean
public RetryTemplate retryTemplate() {
RetryTemplate retryTemplate = new RetryTemplate();
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
backOffPolicy.setBackOffPeriod(2000); // 2 seconds delay
retryTemplate.setBackOffPolicy(backOffPolicy);
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(3);
retryTemplate.setRetryPolicy(retryPolicy);
return retryTemplate;
}
}
```
Then use it in your service:
```java
@Service
public class MyService {
@Autowired
private RetryTemplate retryTemplate;
public String callExternalService() {
return retryTemplate.execute(context -> {
// Your code here
return externalService.call();
});
}
}
```
## 6. Retry with Circuit Breaker Pattern
For more advanced scenarios, consider using Spring Cloud Circuit Breaker or Resilience4j.
## Best Practices
1. Only retry on transient failures (network issues, temporary unavailability)
2. Set reasonable max attempts and delays
3. Consider exponential backoff for distributed systems
4. Always implement a recovery mechanism
5. Monitor and log retry attempts
Would you like me to elaborate on any specific aspect of the retry implementation?
@luismendes070
Copy link
Author

DeepSeek prompt:"Explique fallback"

Entendendo o Fallback no Spring Retry

O fallback é um mecanismo de recuperação que é executado quando todas as tentativas de retentativa (@Retryable) falham. Ele fornece uma resposta alternativa ou um caminho alternativo quando o serviço principal não consegue ser executado com sucesso após várias tentativas.

Como o Fallback Funciona

  1. O método principal é executado e falha
  2. O Spring Retry faz novas tentativas conforme configurado
  3. Se todas as tentativas falharem, o método de fallback (@Recover) é invocado

Implementação Básica

@Service
public class PaymentService {

    @Retryable(value = PaymentException.class, maxAttempts = 3)
    public PaymentResult processPayment(PaymentRequest request) {
        // Tenta processar o pagamento
        return paymentGateway.process(request);
    }

    @Recover
    public PaymentResult fallbackProcessPayment(PaymentException e, PaymentRequest request) {
        // Lógica alternativa quando todas as tentativas falham
        log.error("Falha ao processar pagamento após 3 tentativas", e);
        return new PaymentResult("FAILED", "Sistema de pagamento indisponível");
    }
}

Regras Importantes do Fallback

  1. Assinatura do método: O método de fallback deve ter:

    • O mesmo tipo de retorno do método original
    • O tipo de exceção como primeiro parâmetro
    • Os mesmos parâmetros do método original (opcional)
  2. Múltiplos fallbacks: Você pode ter vários métodos de fallback para diferentes exceções:

@Recover
public PaymentResult fallbackForTimeout(PaymentTimeoutException e, PaymentRequest request) {
    // Lógica específica para timeout
}

@Recover
public PaymentResult fallbackForNetwork(PaymentNetworkException e, PaymentRequest request) {
    // Lógica específica para erro de rede
}

Quando Usar Fallback

  1. Serviços externos indisponíveis: Retornar dados cacheados ou valores padrão
  2. Tempo limite esgotado: Executar uma lógica simplificada local
  3. Erros temporários: Gravar em uma fila para processamento posterior

Exemplo Prático Completo

@Service
public class WeatherService {

    @Retryable(value = {WeatherApiException.class}, 
              maxAttempts = 4,
              backoff = @Backoff(delay = 1000, multiplier = 2))
    public WeatherData getWeather(String city) {
        // Simula chamada a API externa
        if(Math.random() > 0.3) {
            throw new WeatherApiException("Erro na API de clima");
        }
        return new WeatherData(city, 22.5, "Ensolarado");
    }

    @Recover
    public WeatherData getWeatherFallback(WeatherApiException e, String city) {
        // Retorna dados cacheados ou padrão quando a API falha
        log.warn("Usando fallback para clima de " + city);
        return new WeatherData(city, 0.0, "Dados indisponíveis");
    }
}

Boas Práticas com Fallback

  1. Log adequado: Sempre registre quando o fallback for acionado
  2. Mantenha a semântica: O fallback deve retornar algo semanticamente similar ao método original
  3. Evite complexidade: O fallback deve ser simples e confiável
  4. Teste separadamente: Garanta que seu fallback funciona independentemente do método principal

O fallback é essencial para construir sistemas resilientes que podem lidar com falhas temporárias sem impactar drasticamente a experiência do usuário final.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment