404 while using Spring cloud FeignClients
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
rayman
Updated on July 20, 2022Comments
-
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.