I am trying to build a simple flow where my flow starts of by receiving a HTTP Post Request VIA a HTTP Inbound Channel Adapter and publishes it to a 'SubscribableChannel'. There could be 'N' number of consumers subscribed to this channel. The picture below shows the flow.
I am trying to use Spring DSL to configure this flow and have been having trouble making it work. Below is my code.
@Bean
public IntegrationFlow receiveHttpPost() {
return IntegrationFlows.from(Http.inboundChannelAdapter("/receive")
.mappedRequestHeaders("*")
.requestChannel(httpInAdapterPubSubChannel()))
.transform(new ObjectToStringTransformer())
.get();
}
@Bean
public SubscribableChannel httpInAdapterPubSubChannel()
{
return MessageChannels.publishSubscribe("httpInAdapterPubSubChannel")
.get();
}
@Bean
public IntegrationFlow subscriber1() {
return IntegrationFlows.from(httpInAdapterPubSubChannel())
.handle( message -> System.out.println("Enrich Headers based on Payload...."))
.get();
}
@Bean
public IntegrationFlow subscriber2() {
return IntegrationFlows.from(httpInAdapterPubSubChannel())
.handle( message -> System.out.println("Save Payload to Audit Table..."))
.get();
}
When I run this flow, I get "Failed to handle Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available".
o.s.i.channel.PublishSubscribeChannel : preSend on channel 'httpInAdapterPubSubChannel', message: GenericMessage [payload=Test, headers={content-length=4, http_requestMethod=POST, accept-language=en-US,en;q=0.8, accept=*/*, host=localhost:8080, http_requestUrl=http://localhost:8080/receive, connection=keep-alive, content-type=text/plain;charset=UTF-8, id=2c6ee729-96ee-1ae5-be31-a9bc56092758, cache-control=no-cache, accept-encoding=gzip, deflate, br, user-agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36, timestamp=1484457726393}]
o.s.i.t.MessageTransformingHandler : org.springframework.integration.transformer.MessageTransformingHandler#0 received message: GenericMessage [payload=Test, headers={content-length=4, http_requestMethod=POST, accept-language=en-US,en;q=0.8, accept=*/*, host=localhost:8080, http_requestUrl=http://localhost:8080/receive, connection=keep-alive, content-type=text/plain;charset=UTF-8, id=2c6ee729-96ee-1ae5-be31-a9bc56092758, cache-control=no-cache, accept-encoding=gzip, deflate, br, user-agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36, timestamp=1484457726393}]
o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.messaging.MessagingException: Failed to handle Message; nested exception is org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available] with root cause
org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:287) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.integration.handler.AbstractMessageProducingHandler.produceOutput(AbstractMessageProducingHandler.java:212) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutputs(AbstractMessageProducingHandler.java:129) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:115) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.integration.dispatcher.BroadcastingDispatcher.invokeHandler(BroadcastingDispatcher.java:236) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.integration.dispatcher.BroadcastingDispatcher.dispatch(BroadcastingDispatcher.java:185) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:423) ~[spring-integration-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115) ~[spring-messaging-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45) ~[spring-messaging-4.3.5.RELEASE.jar:4.3.5.RELEASE]
It is very evident that I am doing something VERY wrong here. I have tried to find examples showing "Publish Subscribe Channel" VIA Spring Integration DSL OR Java Configuration. Unfortunately, I could not find any :-/. I would wholeheartedly appreciate if any one can provide me with an example and help me find out what is wrong with the flow I have.
One other observation I made was, "When I removed the Subscribers 'subscriber1' and 'subscriber2'", I still get the same error. So that means, there is something wrong that I am doing when configuring y HttpInboundAdapter.
Also, IF I switch the 'httpInAdapterPubSubChannel' to direct, and only have a single route flow (with out branching), things work OK.
.transform(new ObjectToStringTransformer())
is trying to send the result someplace but it doesn't know where - the inbound adapter does not expect a reply and the transformer has nowhere to send the data.
Perhaps you meant something like this...
@Bean
public IntegrationFlow receiveHttpPost() {
return IntegrationFlows.from(Http.inboundChannelAdapter("/receive")
.mappedRequestHeaders("*"))
.transform(new ObjectToStringTransformer())
.channel(httpInAdapterPubSubChannel())
.get();
}
i.e. send the result of the transformer to the pub/sub channel.
The DSL reference has several examples; here and here for example.