Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Fallback method retorna erro 500 Internal Server Error

Boa noite, ao realizar teste no postaman, na chamada do do endpoint http://localhost:8082/pagamentos-ms/pagamentos/2/confirmar. O fallback method é chamado, contudo fica caindo no erro 500 Server Error for HTTP PATCH "/pagamentos-ms/pagamentos/2/confirmar", visto no log do gatway. ![](Insira aqui a descrição dessa imagem para ajudar na acessibilidade ).

Erro apresentado no Postman. ![](Insira aqui a descrição dessa imagem para ajudar na acessibilidade ).

PagamentoController

package br.com.alurafood.controller;

import br.com.alurafood.domain.pagamento.*;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import jakarta.transaction.Transactional;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;

@RestController
@RequestMapping("/pagamentos")
public class PagamentoController {

    @Autowired
    private PagamentoRepository pagamentoRepository;

    @Autowired
    private PagamentoService pagamentoService;

    @PatchMapping("/{id}/confirmar")
    @CircuitBreaker(name = "atualizaPedido", fallbackMethod = "pagamentoAutorizadoComIntegracaoPendente")
    public void confirmarPagamento(@PathVariable @NotNull Long id){
        pagamentoService.confirmarPagamento(id);
    }

    public void pagamentoAutorizadoComIntegracaoPendente(Long id, Exception e){
        pagamentoService.alteraStatus(id);
    }
}

PagamentoService

package br.com.alurafood.domain.pagamento;

import br.com.alurafood.http.PedidoClient;
import jakarta.persistence.EntityNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
public class PagamentoService {

    @Autowired
    private PagamentoRepository pagamentoRepository;

    @Autowired
    private PedidoClient pedidoClient;

    public void confirmarPagamento(Long id){
        Optional<Pagamento> pagamento = pagamentoRepository.findById(id);

        if(!pagamento.isPresent()){
            throw new EntityNotFoundException();
        }
        pagamento.get().mudarStatus(Status.CONFIRMADO);
        pagamentoRepository.save(pagamento.get());
        pedidoClient.atualizaPagamento(pagamento.get().getPedidoId());

    }

PedidoClient

package br.com.alurafood.http;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@FeignClient("pedidos-ms")
public interface PedidoClient {

    @RequestMapping(method = RequestMethod.PUT, value = "/pedidos/{id}/pago")
    void atualizaPagamento(@PathVariable Long id);
}

TratadorDeErros

package br.com.alurafood.infrastructure.exception;

import org.springframework.web.bind.annotation.RestControllerAdvice;
import jakarta.persistence.EntityNotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;

@RestControllerAdvice
public class TratadorDeErros {

    @ExceptionHandler(EntityNotFoundException.class)
    public ResponseEntity tratarErro404() {
        return ResponseEntity.notFound().build();
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity tratarErro400(MethodArgumentNotValidException ex) {
        var erros = ex.getFieldErrors();
        return ResponseEntity.badRequest().body(erros.stream().map(DadosErroValidacao::new).toList());
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity tratarErro400(HttpMessageNotReadableException ex) {
        return ResponseEntity.badRequest().body(ex.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity tratarErro500(Exception ex) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Erro: " +ex.getLocalizedMessage());
    }

    private record DadosErroValidacao(String campo, String mensagem) {
        public DadosErroValidacao(FieldError erro) {
            this(erro.getField(), erro.getDefaultMessage());
        }
    }
}

Link do projeto Github: https://github.com/joelsoncoelho/pagamentos-microservices

3 respostas

Oi! belezinha? o código que você compartilhou me parce certinho em termos de estrutura geral, mas o problema que você está enfrentando pode estar relacionado ao tratamento de erros ou à lógica de fallback do Resilience4j.

  1. Fallback Method: O método pagamentoAutorizadoComIntegracaoPendente deve ter a mesma assinatura do método principal confirmarPagamento e deve aceitar os mesmos parâmetros. Certifique-se de que a assinatura está correta.

  2. Logging: Adicione logs no método pagamentoAutorizadoComIntegracaoPendente para verificar se ele está sendo chamado corretamente e se está executando a lógica desejada. Isso ajudará a entender se o fallback está sendo acionado e se há algum problema na lógica do fallback.

  3. Tratamento de Exceção: No método confirmarPagamento, você está lançando uma EntityNotFoundException se o pagamento não estiver presente. Certifique-se de que o Resilience4j está capturando corretamente essa exceção como uma falha para acionar o fallback. Além disso, verifique se o fallback está tratando a exceção corretamente.

  4. Erro 500: O log indica um erro 500, o que geralmente é um erro interno do servidor. Verifique os logs detalhados da aplicação para identificar a causa raiz do erro. Pode ser útil adicionar logs dentro do método confirmarPagamento para entender em qual parte do código o erro está ocorrendo.

Além disso, certifique-se de que todos os componentes, como o Feign Client (PedidoClient), estão configurados corretamente e que o serviço de pedidos (pedidos-ms) está disponível.

Recomendo realizar essas verificações e adicionar logs adicionais para rastrear o fluxo de execução e identificar a origem do problema. Se você ainda enfrentar dificuldades, compartilhe mais detalhes sobre os logs de erro específicos para que eu possa fornecer uma ajuda mais precisa.

Boa noite, Todos os procedimentos acima foram verificado, e continua a não funcionar.

Segue erro no postman ![](Insira aqui a descrição dessa imagem para ajudar na acessibilidade )

Segue erro do terminal de Pagamentos.

feign.FeignException$ServiceUnavailable: [503] during [PUT] to [http://pedidos-ms/pedidos/1/pago] [PedidoClient#atualizaPagamento(Long)]: [Load balancer does not contain an instance for the service pedidos-ms]
    at feign.FeignException.serverErrorStatus(FeignException.java:265) ~[feign-core-12.4.jar:na]
    at feign.FeignException.errorStatus(FeignException.java:206) ~[feign-core-12.4.jar:na]
    at feign.FeignException.errorStatus(FeignException.java:194) ~[feign-core-12.4.jar:na]
    at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:104) ~[feign-core-12.4.jar:na]
    at feign.ResponseHandler.decodeError(ResponseHandler.java:136) ~[feign-core-12.4.jar:na]
    at feign.ResponseHandler.handleResponse(ResponseHandler.java:70) ~[feign-core-12.4.jar:na]
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114) ~[feign-core-12.4.jar:na]
    at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-12.4.jar:na]
    at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:96) ~[feign-core-12.4.jar:na]
    at jdk.proxy4/jdk.proxy4.$Proxy144.atualizaPagamento(Unknown Source) ~[na:na]
    at br.com.alurafood.pagamentos.service.PagamentoService.confirmarPagamento(PagamentoService.java:71) ~[classes/:na]
    at br.com.alurafood.pagamentos.controller.PagamentoController.confirmarPagamento(PagamentoController.java:61) ~[classes/:na]
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:578) ~[na:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-6.0.13.jar:6.0.13]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-6.0.13.jar:6.0.13]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.0.13.jar:6.0.13]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884) ~[spring-webmvc-6.0.13.jar:6.0.13]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-6.0.13.jar:6.0.13]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.0.13.jar:6.0.13]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081) ~[spring-webmvc-6.0.13.jar:6.0.13]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974) ~[spring-webmvc-6.0.13.jar:6.0.13]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011) ~[spring-webmvc-6.0.13.jar:6.0.13]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:888) ~[spring-webmvc-6.0.13.jar:6.0.13]
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.15.jar:6.0]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) ~[tomcat-embed-core-10.1.15.jar:10.1.15]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.15.jar:10.1.15]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.15.jar:10.1.15]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.15.jar:10.1.15]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.15.jar:10.1.15]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.0.13.jar:6.0.13]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.13.jar:6.0.13]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.15.jar:10.1.15]
solução!

Boa tarde, conseguir resolver o problemas. Era a versão do resilience4j. Como meu projeto é usando java 17 e spring 3.

<dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-spring-boot3</artifactId>
            <version>2.1.0</version>
        </dependency>