Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Feign ErrorDecoder : retrieve the original message

I use a ErrorDecoder to return the right exception rather than a 500 status code.

Is there a way to retrieve the original message inside the decoder. I can see that it is inside the FeignException, but not in the decode method. All I have is the 'status code' and a empty 'reason'.

public class CustomErrorDecoder implements ErrorDecoder {

    private final ErrorDecoder errorDecoder = new Default();

    @Override
    public Exception decode(String s, Response response) {

        switch (response.status()) {

            case 404:
                return new FileNotFoundException("File no found");
            case 403:
                return new ForbiddenAccessException("Forbidden access");
        }

        return errorDecoder.decode(s, response);
    }
}

Here the original message : "message":"Access to the file forbidden"

feign.FeignException: status 403 reading ProxyMicroserviceFiles#getUserRoot(); content:
{"timestamp":"2018-11-28T17:34:05.235+0000","status":403,"error":"Forbidden","message":"Access to the file forbidden","path":"/root"}

Also I use my FeignClient interface like a RestController so I don't use any other Controler populated with the proxy that could encapsulate the methods calls.

   @RestController
   @FeignClient(name = "zuul-server")
   @RibbonClient(name = "microservice-files")

   public interface ProxyMicroserviceFiles {

                @GetMapping(value = "microservice-files/root")
                Object getUserRoot();

                @GetMapping(value = "microservice-files/file/{id}")
                Object getFileById(@PathVariable("id") int id);

    }
like image 392
Monsio Jérémie Béhi Avatar asked Nov 28 '18 17:11

Monsio Jérémie Béhi


People also ask

How do you intercept feign response?

If there is a mechanism to intercept Feign's request object and response object, the request header and response header can be obtained, and the request header and response header can be used to transfer data.

How do you catch feign exception?

You can catch feign client exceptions by catching HystrixRuntimeException and casting the getCause() to FeignClientException .

What is feign error decoder?

Feign is a pluggable and declarative web service client that makes writing web service clients easier. In addition, to Feign annotations, it also supports JAX-RS, and it supports encoders and decoders to provide more customization.

What is feign RetryableException?

public class RetryableException extends FeignException. This exception is raised when the Response is deemed to be retryable, typically via an ErrorDecoder when the status is 503.


2 Answers

Here is a solution, the message is actually in the response body as a stream.

package com.clientui.exceptions;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.io.CharStreams;
import feign.Response;
import feign.codec.ErrorDecoder;
import lombok.*;

import java.io.*;

public class CustomErrorDecoder implements ErrorDecoder {

    private final ErrorDecoder errorDecoder = new Default();

    @Override
    public Exception decode(String s, Response response) {

        String message = null;
        Reader reader = null;

        try {
            reader = response.body().asReader();
            //Easy way to read the stream and get a String object
            String result = CharStreams.toString(reader);
            //use a Jackson ObjectMapper to convert the Json String into a 
            //Pojo
            ObjectMapper mapper = new ObjectMapper();
            //just in case you missed an attribute in the Pojo     
          mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
            //init the Pojo
            ExceptionMessage exceptionMessage = mapper.readValue(result, 
                                                ExceptionMessage.class);

            message = exceptionMessage.message;

        } catch (IOException e) {

            e.printStackTrace();
        }finally {

            //It is the responsibility of the caller to close the stream.
            try {

                if (reader != null)
                    reader.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        switch (response.status()) {

            case 404:
                return new FileNotFoundException(message == null ? "File no found" : 
                                                                     message);
            case 403:
                return new ForbiddenAccessException(message == null ? "Forbidden 
                                                              access" : message);

        }

        return errorDecoder.decode(s, response);
    }

    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    @ToString
    public static class ExceptionMessage{

        private String timestamp;
        private int status;
        private String error;
        private String message;
        private String path;

    }
}
like image 125
Monsio Jérémie Béhi Avatar answered Sep 19 '22 11:09

Monsio Jérémie Béhi


If you want to get the response payload body, with the Feign exception, just use this method:

feignException.contentUTF8();

Example:

    try {
        itemResponse = call(); //method with the feign call
    } catch (FeignException e) {
        logger.error("ResponseBody: " + e.contentUTF8());
    }
like image 43
edubriguenti Avatar answered Sep 19 '22 11:09

edubriguenti