bilak
bilak

Reputation: 4932

loadbalanced ribbon client initialization against discovery service (eureka)

I have service which runs some init scripts after application startup (implemented with ApplicationListener<ApplicationReadyEvent>). In this scripts I need to call another services with RestTemplate which is @LoadBalanced. When the call to service is invoked there's no information about instances of remote service because discovery server was not contacted at that time (I guess).

java.lang.IllegalStateException: No instances available for api-service
    at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:79)

So is there way how to get list of available services from discovery server at application startup, before my init script will execute?

Thanks

edit: The problem is more related to fact, that in current environment (dev) all services are tied together in one service (api-service). So from within api-service I'm trying to call @LoadBalanced client api-service which doesn't know about self? Can I register some listener or something similar to know when api-service (self) will be available?

here are the sample applications. I'm mainly interested how to have working this method

edit2:

Now there could be the solution to create EurekaListener

public static class InitializerListener implements EurekaEventListener {

    private EurekaClient eurekaClient;
    private RestOperations restTemplate;

    public InitializerListener(EurekaClient eurekaClient, RestOperations restTemplate) {
        this.eurekaClient = eurekaClient;
        this.restTemplate = restTemplate;
    }

    @Override
    public void onEvent(EurekaEvent event) {
        if (event instanceof StatusChangeEvent) {
            if (((StatusChangeEvent) event).getStatus().equals(InstanceInfo.InstanceStatus.UP)) {
                ResponseEntity<String> helloResponse = restTemplate.getForEntity("http://api-service/hello-controller/{name}", String.class, "my friend");
                logger.debug("Response from controller is {}", helloResponse.getBody());
                eurekaClient.unregisterEventListener(this);
            }
        }
    }
}

and then register it like this:

EurekaEventListener initializerListener = new InitializerListener(discoveryClient, restTemplate);
discoveryClient.registerEventListener(initializerListener);

However this is only executed only when application is registered to discovery service first time. Next time when I stop the api-service and run it again, event is not published. Is there any other event which can I catch?

Upvotes: 2

Views: 845

Answers (1)

spencergibb
spencergibb

Reputation: 25157

Currently, in Camden and earlier, applications are required to be registered in Eureka before they can query for other applications. Your call is likely too early in the registration lifecycle. There is an InstanceRegisteredEvent that may help. There are plans to work on this in the Dalston release train.

Upvotes: 4

Related Questions