feign-annotation-error-decoder icon indicating copy to clipboard operation
feign-annotation-error-decoder copied to clipboard

Use with Spring Cloud

Open chrisob55 opened this issue 6 years ago • 7 comments

There seems to be an issue when trying to use this within Spring Cloud/Eureka setup. Using the @FeignClient annoation

@FeignClient(name = "myResource", url = "${my.endpoint}", configuration = MyResourceConfig.class)

Defining the AnnotationErrorDecoder in the configuration means it doesn't work. Is there any there way of defining an AnnotationErrorDecoder (ideally leaving out the builderFor(XXXX.class) as this can cause a circular reference?

Thanks,

chrisob55 avatar Aug 25 '18 09:08 chrisob55

Hey @chrisob55 - I'll take a look but I'll need to try to reproduce the issue. Do you by any chance have a zip of a sample of the issue you're seeing? Just trying to reproduce in my IDE.

Thanks, -Fernando

saintf avatar Sep 02 '18 10:09 saintf

Hello, I've found the same problem. Here is a small example to give the idea of what I've tried to do, but failed. All exceptions defined on the @ErrorHandling extends AbstractRequestException. But all requests that mach the error codes fall into the catch of the FeignException.

Client.java

@ErrorHandling(codeSpecific =
    {
        @ErrorCodes( codes = {400}, generate = PayloadException.class),
        @ErrorCodes( codes = {403}, generate = ForbiddenException.class),
        @ErrorCodes( codes = {404}, generate = UnknownResourceException.class),
    },
    defaultException = PayloadException.class
)
@FeignClient(value = "api", url = "${api.path}",
    configuration = ClientConfiguration.class)
public interface Client {

    @RequestMapping(method = RequestMethod.PUT, value = "/path", consumes = "application/json")
    String create(@RequestBody final String payload);

}

Service.java

@RestController
@RequestMapping(path = "/test")
public class Service {

    private final Client client;

    @Autowired
    public Service(final Client client) {
        this.client = client;
    }

    @GetMapping(path = "/a")
    @ResponseBody
    public String makeRequest(@RequestParam final String id) {
        try {
            String body = "";
            externalHouse = this.client.create(body);
        } catch (AbstractRequestException e) {
            log.error(e.getMessage());
        } catch (FeignException e) {
            log.error(e.getMessage());
        }
    }
}

Also, in the ClientConfiguration class, I've defined the following:

    @Bean
    public ErrorDecoder errorDecoder() {
        return AnnotationErrorDecoder.builderFor(Client.class).build();
    }

lucasm0ta avatar Oct 21 '19 23:10 lucasm0ta

Let me give it a try. Can you give me the exact spring dependencies so I can make sure we're on same versions/etc and I can try to debug?

On Mon, 21 Oct 2019, 17:05 Lucas Mota, [email protected] wrote:

Hello, I've found the same problem. Here is a small example to give the idea of what I've tried to do, but failed. All exceptions defined on the @ErrorHandling extends AbstractRequestException. But all requests that mach the error codes fall into the catch of the FeignException. Client.java

@ErrorHandling(codeSpecific = { @ErrorCodes( codes = {400}, generate = PayloadException.class), @ErrorCodes( codes = {403}, generate = ForbiddenException.class), @ErrorCodes( codes = {404}, generate = UnknownResourceException.class), }, defaultException = PayloadException.class ) @FeignClient(value = "api", url = "${api.path}", configuration = ClientConfiguration.class) public interface Client {

@RequestMapping(method = RequestMethod.PUT, value = "/path", consumes = "application/json")
String create(@RequestBody final String payload);

}

Service.java

@RestController @RequestMapping(path = "/test") public class Service {

private final Client client;

@Autowired
public Service(final Client client) {
    this.client = client;
}

@GetMapping(path = "/a")
@ResponseBody
public String makeRequest(@RequestParam final String id) {
    try {
        String body = "";
        externalHouse = this.client.create(body);
    } catch (AbstractRequestException e) {
        log.error(e.getMessage());
    } catch (FeignException e) {
        log.error(e.getMessage());
    }
}

}

Also, in the ClientConfiguration class, I've defined the following:

@Bean
public ErrorDecoder errorDecoder() {
    return AnnotationErrorDecoder.builderFor(Client.class).build();
}

— You are receiving this because you were assigned. Reply to this email directly, view it on GitHub https://github.com/OpenFeign/feign-annotation-error-decoder/issues/9?email_source=notifications&email_token=ADJ2TCSPCJPGJWC5NK3GAZ3QPYYT7A5CNFSM4FRRI2J2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEB4CJOI#issuecomment-544744633, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADJ2TCXWS6CB7GC42UUIWYDQPYYT7ANCNFSM4FRRI2JQ .

saintf avatar Oct 22 '19 00:10 saintf

Hi @lucasm0ta ,

maybe you have solved the problem yourself, since it's a long time ago since you've opened this ticket.

The AnnotationErrorDecoder requires methods to be annotated with @ErrorHandling to kick in. So if you annotate your Method simple with @ErrorHandling() it will work.

StefanFellinger avatar Jun 05 '20 11:06 StefanFellinger

It has been quite a long time! I really lost track of this issue as I used another approach at the time. Thank you for the note on this issue. While I'm not currently working with the code with said problem, I hope it helps other users 😄. In case I get back to it, I'll give it a try

lucasm0ta avatar Jun 05 '20 21:06 lucasm0ta

Hello guys I am getting this error when using feign-annotation-error-decoder:1.3.0 spring-cloud-starter-openfeign:2.2.3.RELEASE

***************************
APPLICATION FAILED TO START
***************************

Description:

An attempt was made to call a method that does not exist. The attempt was made from the following location:

    feign.error.ExceptionGenerator.<clinit>(ExceptionGenerator.java:44)

The following method did not exist:

    feign.Request.create(Lfeign/Request$HttpMethod;Ljava/lang/String;Ljava/util/Map;Lfeign/Request$Body;)Lfeign/Request;     

My Error decoder is as following:

@Bean
public ErrorDecoder errorDecoder() {
    return AnnotationErrorDecoder.builderFor(Client.class).build();
 }

My problem is that feign returns an empty body for 401 response (this is my testing use case, the service returns a custom response) I don't know all the error codes the service will return. I also tried creating a custom ErrorDecoder but inside the decode method the body of the Response object is also null.

public ErrorDecoder errorDecoder() {
    return new FeignClientExceptionErrorDecoder();
}

I'd like to know if feign-annotation-error-decoder works for you guys with the latest version of Spring Cloud. Mi intention is to propagate the response for http error status codes. This json response change for the same error code according to the input data.

Greetings.

jnm-ronquillo avatar Jul 03 '20 06:07 jnm-ronquillo

I'm facing the same error as @jnm-ronquillo. Any thoughts on that?

EDIT: I was able to make it work, by using these specific versions:

implementation("org.springframework.cloud:spring-cloud-starter-openfeign:2.2.2.RELEASE")
implementation("io.github.openfeign:feign-annotation-error-decoder:1.3.0")
implementation("io.github.openfeign:feign-core:10.2.0")

brunapereira avatar Aug 14 '20 03:08 brunapereira