Especialização em Backend com Java & Spring Boot • Demonstrações Práticas Compiláveis


💻 Código de Exemplo 01 — Circuit Breaker com Fallback e Assinatura Compatível

package com.empresa.api.service;

import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.stereotype.Service;

@Service
public class PaymentResilienceService {

    @CircuitBreaker(name = "pagamentoService", fallbackMethod = "fallbackPagamento")
    public String processarPagamento(Long pedidoId) {
        if (pedidoId % 5 == 0) {
            throw new RuntimeException("Gateway de pagamento fora do ar");
        }
        return "PAGAMENTO_APROVADO";
    }

    // Mesma assinatura de retorno + Throwable no final: contrato exigido pelo Resilience4j.
    private String fallbackPagamento(Long pedidoId, Throwable t) {
        return "PAGAMENTO_EM_PROCESSAMENTO_OFFLINE";
    }
}

💻 Código de Exemplo 02 — Retry com Backoff Exponencial Combinado a Bulkhead

package com.empresa.api.service;

import io.github.resilience4j.bulkhead.annotation.Bulkhead;
import io.github.resilience4j.retry.annotation.Retry;
import org.springframework.stereotype.Service;

@Service
public class EstoqueConsultaService {

    private int tentativas = 0;

    @Retry(name = "consultaEstoque")
    public boolean checarEstoque(Long produtoId) {
        tentativas++;
        System.out.println("Tentativa #" + tentativas + " de consulta de estoque...");
        if (tentativas < 3) {
            throw new RuntimeException("Timeout transitório na consulta de estoque");
        }
        return true;
    }

    // Isola no máximo 5 execuções concorrentes deste método, protegendo o pool
    // de threads compartilhado de ser esgotado por relatórios pesados e lentos.
    @Bulkhead(name = "relatoriosPesados")
    public void gerarRelatorioMensal(Long lojaId) {
        System.out.println("Processando relatório pesado da loja " + lojaId + " em pool isolado.");
    }
}

💻 Código de Exemplo 03 — Monitoramento Programático do Estado do Circuit Breaker

package com.empresa.api.service;

import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import org.springframework.stereotype.Component;

@Component
public class CircuitBreakerMonitor {

    private final CircuitBreakerRegistry registry;

    public CircuitBreakerMonitor(CircuitBreakerRegistry registry) {
        this.registry = registry;

        // Reage em tempo real a transições de estado (ex.: disparar alerta ao abrir).
        registry.getAllCircuitBreakers().forEach(cb ->
            cb.getEventPublisher().onStateTransition(evento ->
                System.out.println("Circuit Breaker '" + cb.getName() + "' mudou de " +
                    evento.getStateTransition().getFromState() + " para " +
                    evento.getStateTransition().getToState())));
    }

    public void listarEstadoAtual() {
        registry.getAllCircuitBreakers().forEach(cb ->
            System.out.println("Circuit Breaker " + cb.getName() + " Estado: " + cb.getState())
        );
    }
}