404 while using Spring cloud FeignClients

11,795

Solution 1

Your code looks backwards to me.

The feign client for the baggage service should be declared in the flight service and the baggage service should have a controller that responds on the URL you map in your baggage service client, you should not implement the interface annotated with @FeignClient.

The setup you have now will not have any controller listening on /baggage/list/{flightId} in the baggage service and no Feign client in flight service - the whole point of Feign is to call methods on an interface instead of manually handling URLs, Spring Cloud takes care of auto-instantiating the interface implementation and will use Eureka for discovery.

Try this (or modify so it fits your real world app):

Flight Service:

FlightIntegrationService.java:

@Component
public class FlightIntegrationService {

    @Autowired
    BaggageService baggageService;

    public String getBaggageListById(String id) {
        return baggageService.getBaggageListByFlightId(id);
    }
}

BaggageService.java:

@FeignClient("baggage-service")
public interface BaggageService {

    @RequestMapping(method = RequestMethod.GET, value = "/baggage/list/{flight_id}")
    List<String> getBaggageListByFlightId(@PathVariable("flight_id") String flightId);   
}

Baggage Service:

BaggageController.java:

@RestController
public class BaggageController {

    @RequestMapping("/baggage/list/{flightId}")
    public List<String> getBaggageListByFlightId(@PathVariable String flightId) {
        return Arrays.asList("2,3,4");
    }
}

Remove BaggageService.java and BaggageServiceImpl.java from the Baggage Service

Solution 2

registryService.getServiceUrl("baggage-service", ... replace with

registryService.getServiceUrl("baggage-service")

make sure that matches the right name

remove the localhost part

or only use the http://local part

It only worked for us if you have just the name of the service listed in eureka dashboard, not both

Share:
11,795
rayman
Author by

rayman

Updated on July 20, 2022

Comments

  • rayman
    rayman almost 2 years

    This is my setup:

    First service(FlightIntegrationApplication) which invoke second service(BaggageServiceApplication) using FeignClients API and Eureka.

    Project on github: https://github.com/IdanFridman/BootNetflixExample

    First service:

    @SpringBootApplication
    @EnableCircuitBreaker
    @EnableDiscoveryClient
    @ComponentScan("com.bootnetflix")
    public class FlightIntegrationApplication {
    
        public static void main(String[] args) {
            new SpringApplicationBuilder(FlightIntegrationApplication.class).run(args);
        }
    
    }
    

    in one of the controllers:

        @RequestMapping("/flights/baggage/list/{id}")
        public String getBaggageListByFlightId(@PathVariable("id") String id) {
            return flightIntegrationService.getBaggageListById(id);
        }
    

    FlightIntegrationService:

        public String getBaggageListById(String id) {
            URI uri = registryService.getServiceUrl("baggage-service", "http://localhost:8081/baggage-service");
            String url = uri.toString() + "/baggage/list/" + id;
            LOG.info("GetBaggageList from URL: {}", url);
    
            ResponseEntity<String> resultStr = restTemplate.getForEntity(url, String.class);
            LOG.info("GetProduct http-status: {}", resultStr.getStatusCode());
            LOG.info("GetProduct body: {}", resultStr.getBody());
            return resultStr.getBody();
    
        }
    

    RegistryService:

    @Named
    public class RegistryService {
    
        private static final Logger LOG = LoggerFactory.getLogger(RegistryService.class);
    
    
        @Autowired
        LoadBalancerClient loadBalancer;
    
        public URI getServiceUrl(String serviceId, String fallbackUri) {
            URI uri;
            try {
                ServiceInstance instance = loadBalancer.choose(serviceId);
                uri = instance.getUri();
                LOG.debug("Resolved serviceId '{}' to URL '{}'.", serviceId, uri);
    
            } catch (RuntimeException e) {
                // Eureka not available, use fallback
                uri = URI.create(fallbackUri);
                LOG.error("Failed to resolve serviceId '{}'. Fallback to URL '{}'.", serviceId, uri);
            }
    
            return uri;
        }
    
    }
    

    And this is the second service (baggage-service):

    BaggageServiceApplication:

    @Configuration
    @ComponentScan("com.bootnetflix")
    @EnableAutoConfiguration
    @EnableEurekaClient
    @EnableFeignClients
    public class BaggageServiceApplication {
    
    
        public static void main(String[] args) {
            new SpringApplicationBuilder(BaggageServiceApplication.class).run(args);
        }
    
    }
    

    BaggageService:

    @FeignClient("baggage-service")
    public interface BaggageService {
    
        @RequestMapping(method = RequestMethod.GET, value = "/baggage/list/{flight_id}")
        List<String> getBaggageListByFlightId(@PathVariable("flight_id") String flightId);
    
    
    }
    

    BaggageServiceImpl:

    @Named
    public class BaggageServiceImpl implements BaggageService{
    
    ....
    
        @Override
        public List<String> getBaggageListByFlightId(String flightId) {
            return Arrays.asList("2,3,4");
        }
    
    }
    

    When invoking the rest controller of flight integration service I get:

    2015-07-22 17:25:40.682  INFO 11308 --- [  XNIO-2 task-3] c.b.f.service.FlightIntegrationService   : GetBaggageList from URL: http://X230-Ext_IdanF:62007/baggage/list/4
    2015-07-22 17:25:43.953 ERROR 11308 --- [  XNIO-2 task-3] io.undertow.request                      : UT005023: Exception handling request to /flights/baggage/list/4
    
    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 404 Not Found
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
    

    Any idea ?

    Thanks, ray.