5

I'am trying to send a simple message using "spring cloud stream" to the rabbitmq. Basically code looks like this:

@EnableBinding(Source.class)
@SpringBootApplication
public class SourceApplication {

    public static void main(String[] args) {
        SpringApplication.run(SourceApplication.class, args);
    }

    @Autowired Source source;

    @PostConstruct
    public void init() {
        source.send(MessageBuilder.withPayload("payload").build());
    }
}

then I get this error message:

org.springframework.messaging.MessageDeliveryException: Dispatcher has no subscribers for channel 'unknown.channel.name'.; nested exception is org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers, failedMessage=GenericMessage [payload=******, headers={id=c60dd5be-6576-99d5-fd1b-b1cb94c191c1, timestamp=1488651422892}]
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:93)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:423)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:373)

However, if I add some delay, before sending a message (just second or few), it works ok. My question is: how can I wait before spring completely initialize message channels and then send a message?

Maburo
  • 83
  • 1
  • 7

2 Answers2

7

@PostConstruct is triggered too early (when the configuration bean is created, but before the context is started and the binding takes place). What you want is to trigger the sending of the message once the context is completely initialized, or at least after the output channels are bound.

You have a few options, all relying on the creation of an additional bean:

  1. To use the SmartLifecycle support from Spring (make sure that isAutoStartup returns true by default and the phase is zero - the default - so that the bean is started after outputs are bound).

  2. Use an ApplicationListener for ContextRefreshedEvent.

  3. Since this is a Spring Boot application you can use an ApplicationRunner bean (which gets invoked after the context has been created).

Marius Bogoevici
  • 2,380
  • 1
  • 13
  • 14
0

You might look into Spring's Task Execution and Scheduling features.

In particular, it sounds like you want something like what section 34.4 covers.

Also, I spotted this answer to a similar question.

Community
  • 1
  • 1
kevin628
  • 3,458
  • 3
  • 30
  • 44
  • as I sad: I can add delay... but, what I need is some kind of event listner to be sure that this message channel is ready – Maburo Mar 04 '17 at 19:18