8

I am currently just checking how to use Feign as Declarative REST client in one of my project.

following is Feign Client

@FeignClient(name = "SEARCHCABMS",configuration = AppFeignConfiguration.class)
       public interface SearchCabMsClient {

        @RequestMapping(value = "api/searchcab/locationcabtimedetail/search/getCabForLocationAfterTimeSlot", method = RequestMethod.GET)
        String  searchCabDetails(@PathVariable("fromDate") String fromDate, 
                                @PathVariable("locationId") long locationId,
                                @PathVariable("isdeleted") byte isdeleted,
                                @PathVariable("hourforbooking")int hourforbooking);
    }

This interface is autowired in one service

@Autowired
SearchCabMsClient restService;

Added EnableFeignClients to SpringBootApplication

@EnableFeignClients(basePackages = {"com.gp.cabbooking.services.feign"})

Dependencies,parent etc in pom.xml

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.5.RELEASE</version>
</parent>

dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

I can able to see while debugging spring create proxy for my feign client i tried calling this service with the help of ribbon and it is working fine but when i execute method define in my feign client . i am getting feign.FeignException: status 404 reading

feign.FeignException: status 404 reading SearchCabMsClient#searchCabDetails(String,long,byte,int)
    at feign.FeignException.errorStatus(FeignException.java:62) ~[feign-core-8.16.2.jar:8.16.2]
    at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:91) ~[feign-core-8.16.2.jar:8.16.2]
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:134) ~[feign-core-8.16.2.jar:8.16.2]
    at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76) ~[feign-core-8.16.2.jar:8.16.2]
    at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:97) ~[feign-hystrix-8.16.2.jar:8.16.2]
    at com.netflix.hystrix.HystrixCommand$1.call(HystrixCommand.java:293) ~[hystrix-core-1.5.3.jar:1.5.3]
    at com.netflix.hystrix.HystrixCommand$1.call(HystrixCommand.java:289) ~[hystrix-core-1.5.3.jar:1.5.3]
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46) ~[rxjava-1.1.5.jar:1.1.5]
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35) ~[rxjava-1.1.5.jar:1.1.5]
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:50) ~[rxjava-1.1.5.jar:1.1.5]
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.1.5.jar:1.1.5]
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:50) ~[rxjava-1.1.5.jar:1.1.5]
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.1.5.jar:1.1.5]
    at rx.Observable.unsafeSubscribe(Observable.java:8460) ~[rxjava-1.1.5.jar:1.1.5]
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51) ~[rxjava-1.1.5.jar:1.1.5]
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35) ~[rxjava-1.1.5.jar:1.1.5]
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:50) ~[rxjava-1.1.5.jar:1.1.5]
PAA
  • 1
  • 46
  • 174
  • 282
Ganesh Pol
  • 413
  • 1
  • 8
  • 29

5 Answers5

7

You need to create a feign.ErrorDecoder. Please read this for more information https://github.com/spring-cloud/spring-cloud-openfeign/issues/118

You can also add decode404=true in your FeignClient annotation definition.

The_Cute_Hedgehog
  • 1,280
  • 13
  • 22
2

Have you defined the url of the service you reach to using this feign client? 404 is a not found issue.

  @FeignClient(name = "SEARCHCABMS", url = "${SEARCHCABMS.service.url}", 
  configuration = ClientConfiguration.class)
  public interface SearchCabMsClient {

  }

Having a reference holder in url helps to externalize it and configure for each environment.

If you did configured the URL, double the check the rest endpoint.

Seetha
  • 980
  • 1
  • 8
  • 27
  • spring cloud feign should be invoked based on the app name with out using url right? – Abdul Jul 24 '19 at 10:59
  • I am not sure what you mean by that? As far as this answer goes, feign client either from openfeign or spring cloud, doesn't matter. Its just a http client implementation. So you do need to provide the URL it needs to connect to. – Seetha Aug 02 '19 at 21:42
1

I had the same problem. It is a routing issue. Just add / at the start in @RequestMapping path in FeignClient. Also, path variables are not defined in the path. I recommend define they as @RequestParam. Then the path is correct except / at the start.

@FeignClient(name = "SEARCHCABMS",configuration = AppFeignConfiguration.class)
   public interface SearchCabMsClient {

    @RequestMapping(value = "/api/searchcab/locationcabtimedetail/search/getCabForLocationAfterTimeSlot/{fromDate}/{locationId}/{isdeleted}/{hourforbooking}", method = RequestMethod.GET)
    String  searchCabDetails(@PathVariable("fromDate") String fromDate, 
                            @PathVariable("locationId") long locationId,
                            @PathVariable("isdeleted") byte isdeleted,
                            @PathVariable("hourforbooking")int hourforbooking);
}
Valeriy K.
  • 2,616
  • 1
  • 30
  • 53
1

Most of the answers suggest putting the url attribute to @FeignClient, but when the architecture involves registering the service (Eureka Client) with the Eureka Server, I think, there is no liberty to use the url attribute.

It is the service-id or the eureka-id that has to be used for the purpose of rest calls.
So, with the client-side discovery architecture,

@FeignClient(name = "service-id", url = "${service.url}", configuration=SomeConfig.class)

may no longer be the scalable solution to the
status 404 reading IFeignClient#someControllerMethod() error.

I faced the same error in my client-side discovery architecture app. The issue was this entry in the application.yml file:

server:
  servlet:
    context-path: /myapp

Removing it helped resolve the issue by correct url. The exact declaration that my working app has: @FeignClient(name="${service-id}")

Hope this helps someone with similar issue.

adarsh
  • 1,393
  • 1
  • 8
  • 16
  • 1
    Instead of removing context-path from application.yml you could have added /myapp as a prefix path to declarative methed of Feign client for example @RequestMapping(value = "/myapp/remaining path", method = RequestMethod.GET) String feignMethod(...); – abhinav kumar May 31 '21 at 15:23
0

If you have set the server.servlet.context-path: ##some name##, remove it and set the application name displayed in EUREKA server home page.