Spring cloud stream - отправить сообщение после инициализации приложения

Я пытаюсь отправить простое сообщение, используя «весенний облачный поток» в rabbitmq. В основном код выглядит так:

@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());
    }
}

то я получаю это сообщение об ошибке:

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)

Однако, если я добавляю некоторую задержку перед отправкой сообщения (всего секунду или несколько), все работает нормально. Мой вопрос: как я могу дождаться, пока весна полностью инициализирует каналы сообщений, а затем отправить сообщение?


person Maburo    schedule 04.03.2017    source источник


Ответы (2)


@PostConstruct срабатывает слишком рано (когда создается bean-компонент конфигурации, но до запуска контекста и выполнения привязки). Что вы хотите, так это инициировать отправку сообщения после полной инициализации контекста или, по крайней мере, после привязки выходных каналов.

У вас есть несколько вариантов, все они основаны на создании дополнительного bean-компонента:

  1. Чтобы использовать поддержку SmartLifecycle из Spring (убедитесь, что isAutoStartup возвращает true по умолчанию, а фаза равна нулю — по умолчанию — чтобы bean-компонент запускался после привязки выходов).

  2. Используйте ApplicationListener вместо ContextRefreshedEvent.

  3. Поскольку это приложение Spring Boot, вы можете использовать bean-компонент ApplicationRunner (который вызывается после создания контекста).

person Marius Bogoevici    schedule 04.03.2017
comment
для меня это не работает, ни для ContextRefreshedEvent, ни для ApplicationReadyEvent. - person sschrass; 05.06.2019

Вы можете изучить функции выполнения задач и планирования Spring. .

В частности, похоже, что вы хотите что-то вроде того, что раздел 34.4 касается.

Кроме того, я заметил этот ответ на аналогичный вопрос.

person kevin628    schedule 04.03.2017
comment
как мне грустно: я могу добавить задержку... но мне нужен какой-то список событий, чтобы быть уверенным, что этот канал сообщений готов - person Maburo; 04.03.2017