Reputation: 1937
I have this very basic setup of IntegrationFlow
with Spring Integration Java DSL:
@IntegrationComponentScan
@EnableIntegration
@Configuration
public class DummyConfig {
@MessagingGateway
public interface DummyGateway {
@Gateway(requestChannel = "dummyInChannel")
void echo(String payload);
}
@Bean(name = "dummyInChannel")
public MessageChannel dummyInChannel() {
return MessageChannels.direct().get();
}
@Bean
public IntegrationFlow dummyFlow() {
return IntegrationFlows.from(dummyInChannel())
.handle(String.class, (payload, headers) -> {
System.out.println(payload);
return "";
})
.get();
}
}
When I try to post a message to my gateway
dummyGateway.echo("test");
I'm getting and exception:
Caused by: org.springframework.messaging.MessageDeliveryException:
Dispatcher has no subscribers for channel 'application.dummyInChannel'.; nested exception
is org.springframework.integration.MessageDispatchingException: Dispatcher
has no subscribers, failedMessage=GenericMessage [payload=test,
headers={replyChannel=nullChannel, id=6e4302e4-95f0-bf5a-c1a3-e8cd587c23fb, timestamp=1643269549272}]
I thought, that doing .handle()
in my flow is exactly subscribing to a channel. Then, why am I getting this exception? How to properly subscribe to my channel in this scenario?
Upvotes: 1
Views: 907
Reputation: 45
public static void main(String[] args) {
SpringApplication application = new SpringApplication(DummyConfig.class);
ConfigurableApplicationContext ctx = application.run(args);
ctx.getBean(DummyGateway.class).echo("MyAwesomeString");
ctx.close();
}
Upvotes: 0
Reputation: 121177
No, the ctor is too early. The beans are created at this point, but they have not started their heavy lifting. You cannot do low-level resources interaction (technically any actions) from the bean initialization phase. You need to wait until application context is fully started. Please, learn a lifecycle of Spring container: https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-lifecycle-processor .
You may implement a SmartLifecycle
, or listener for the ContextStartedEvent
. But bean initialization phase is really too early to start emitting messages.
The QueueChannel
works because it has its own internal buffer to keep messages until they are consumed. And they are consumed when the endpoint is started. In case of DirectChannel
there is no buffer and consumer is called immediately, when we send a message. There is just no subscriber yet on that channel within bean initialization phase.
Upvotes: 1