2

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?

bilak
  • 4,526
  • 3
  • 35
  • 75

1 Answers1

4

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.

spencergibb
  • 24,471
  • 6
  • 69
  • 75
  • even when I change the event to `InstanceRegisteredEvent` I get the same exception (No instances available - I pushed that to github). Is there something else what can help me? I can see that configuration object from event can be cast to `EurekaInstanceConfigBean` and from there I can get the ip address and port of target service, but I think in this case I can't use @LoadBalanced rest template. If I can somehow help you to investigate this issue let me know. I need to have this functionality in current proect. Thank you – bilak Sep 27 '16 at 07:26
  • I've created the listener (see edited question) but there is problem that it's not execute every time the application is restarted. – bilak Sep 27 '16 at 09:13
  • is it possible to listen to some event which is invoked each time application registers to registry server? – bilak Sep 30 '16 at 19:16