Is there any specific reason for spring integration raise this INFO when processing the flow - spring

I created the flow below and it's working normally but all the time this information is printed in the log file.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-5.2.xsd
http://www.springframework.org/schema/integration/http
http://www.springframework.org/schema/integration/http/spring-integration-http-5.2.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<task:executor id="taskExecutorRecursaoRendaVariavel" pool-size="15-20" queue-capacity="100"/>
<task:executor id="taskExecutorProcessamentoRendaVariavel" pool-size="15-20" queue-capacity="100"/>
<task:executor id="taskExecutorSplitterRendaVariavel" pool-size="15-20" queue-capacity="100"/>
<int:channel id="xxx-consolidador-movimentacao-renda-variavel"/>
<int:publish-subscribe-channel id="xxx-consolidador-splitter-recursao-renda-variavel" task-executor="taskExecutorSplitterRendaVariavel"/>
<int:channel id="xxx-consolidador-channel-segrega-renda-variavel"/>
<int:publish-subscribe-channel id="xxx-consolidador-splitter-renda-variavel-recursao-movimentacao" task-executor="taskExecutorRecursaoRendaVariavel"/>
<int:publish-subscribe-channel id="xxx-consolidador-splitter-renda-variavel-processa-movimentacao" task-executor="taskExecutorProcessamentoRendaVariavel"/>
<int:channel id="xxx-consolidador-direct-channel-movimentacao-renda-variavel"/>
<int:channel id="xxx-consolidador-request-ativo-renda-variavel"/>
<int:channel id="xxx-consolidador-request-movimentacao-renda-variavel"/>
<int:channel id="xxx-consolidador-request-notifica-renda-variavel"/>
<int:channel id="xxx-consolidador-filter-channel-renda-variavel"/>
<int-http:outbound-gateway
url="${xxxx.xxxxx.movimentacao-rendavariavel}?startDate={dtInitPosicao}&endDate={dtenddate}&page={page}&recordPerPage=${RECORDS_PER_PAGE:250}&cblc={cblc}&cpfCnpj={cpf}"
http-method="GET"
expected-response-type="br.com.xxxxx.ciar.xxx.xxx.xxx.integration.response.ResponseRendaVariavelMovimentacao"
request-channel="xxx-consolidador-movimentacao-renda-variavel"
reply-channel="xxx-consolidador-splitter-recursao-renda-variavel"
rest-template="restTemplate"
mapped-request-headers="Authorization, cpf, cblc, dtInitPosicao, dtenddate, page">
<int-http:uri-variable name="cpf" expression="headers.cpf"/>
<int-http:uri-variable name="cblc" expression="headers.cblc"/>
<int-http:uri-variable name="dtInitPosicao" expression="headers.dtinitposicao"/>
<int-http:uri-variable name="dtenddate" expression="headers.dtenddate"/>
<int-http:uri-variable name="page" expression="headers.page"/>
</int-http:outbound-gateway>
<int:splitter input-channel="xxx-consolidador-splitter-recursao-renda-variavel"
output-channel="xxx-consolidador-channel-segrega-renda-variavel">
<bean class="br.com.xxx.ciar.xxx.renda.variavel.integration.splitter.SplitterRecursaoRendaVariavel"/>
</int:splitter>
<int:header-value-router id="recursaoRendaVariavel" input-channel="xxx-consolidador-channel-segrega-renda-variavel"
header-name="recursao" resolution-required="false">
<int:mapping value="true" channel="xxx-consolidador-splitter-renda-variavel-recursao-movimentacao"/>
</int:header-value-router>
<int:header-value-router id="processaRendaVariavel" input-channel="agora-consolidador-channel-segrega-renda-variavel"
header-name="processa" resolution-required="false">
<int:mapping value="true" channel="xxxx-consolidador-splitter-renda-variavel-processa-movimentacao"/>
</int:header-value-router>
<int:header-filter input-channel="xxx-consolidador-splitter-renda-variavel-processa-movimentacao"
output-channel="xxx-consolidador-filter-channel-renda-variavel"
header-names="Authorization, authorization"/>
<int:splitter input-channel="xxx-consolidador-filter-channel-renda-variavel"
output-channel="xxx-consolidador-direct-channel-movimentacao-renda-variavel">
<bean class="br.com.xxx.ciar.xxxx.renda.variavel.integration.splitter.RendaVariavelMovimentacaoSplitter"/>
</int:splitter>
<int:header-value-router input-channel="xxx-consolidador-direct-channel-movimentacao-renda-variavel" header-name="type" order="1">
<int:mapping value="ativos" channel="xxx-consolidador-request-ativo-renda-variavel"/>
</int:header-value-router>
<int:header-value-router input-channel="xxx-consolidador-direct-channel-movimentacao-renda-variavel" header-name="type" order="2">
<int:mapping value="posicao" channel="xxx-consolidador-request-movimentacao-renda-variavel"/>
</int:header-value-router>
<int:header-value-router input-channel="xxx-consolidador-direct-channel-movimentacao-renda-variavel" header-name="type" order="3">
<int:mapping value="notifica" channel="xxx-consolidador-request-notifica-renda-variavel"/>
</int:header-value-router>
<int-http:outbound-channel-adapter
http-method="POST"
url="${xxxx.ativos}"
channel="xxx-consolidador-request-ativo-renda-variavel"
rest-template="restTemplate"
mapped-request-headers="Authorization, DESTINO_URL">
</int-http:outbound-channel-adapter>
<int-http:outbound-channel-adapter
http-method="POST"
url="${xxxx.movimento-rendavariavel}"
channel="xxx-consolidador-request-movimentacao-renda-variavel"
rest-template="restTemplate"
mapped-request-headers="Authorization, DESTINO_URL">
</int-http:outbound-channel-adapter>
<int-http:outbound-channel-adapter
http-method="POST"
url="${xxxx.notifica}"
channel="xxx-consolidador-request-notifica-renda-variavel"
rest-template="restTemplate"
mapped-request-headers="Authorization, DESTINO_URL">
</int-http:outbound-channel-adapter>
</beans>
2021-11-05 17:55:16,811 [taskExecutorSplitterRendaVariavel-1] INFO o.s.i.d.UnicastingDispatcher - An exception was thrown by 'bean 'org.springframework.integration.config.RouterFactoryBean#6' for component 'recursaoRendaVariavel'; defined in: 'file []'; from source: ''int:header-value-router' with id='recursaoRendaVariavel''' while handling 'GenericMessage [payload=br.com.bradesco.ciar.agora.renda.variavel.integration.response.ResponseRendaVariavelMovimentacao#2a5ae9, headers={Transfer-Encoding=chunked, http_requestMethod=GET, sequenceNumber=1, processa=true, sequenceSize=2, dtenddate=20211105, Pragma=no-cache, http_statusCode=200 OK, Date=1636145712000, dtinitposicao=20211101, Cache-Control=no-cache, no-store, max-age=0, must-revalidate, cblc=161254, cpf=21333240899, http_requestUrl=http://localhost:8083/renda-variavel/xxxxxxxxxx, contentType=application/json;charset=utf-8, timestamp=1636145716810}]': No channel resolved by router 'recursaoRendaVariavel' and no 'defaultOutputChannel' defined.. Failing over to the next subscriber.

Your <int:channel id="xxx-consolidador-channel-segrega-renda-variavel"/> is a DirectChannel with a UnicastingDispatcher, which has a logic to failover to the next subscriber, if the current one has failed. The logic is like this:
if (!isLast && this.failover) {
logExceptionBeforeFailOver(ex, handler, message);
}
We log that message to inform you that this might not be an expected behavior. For example that was an accident to add another subscriber to this channel. The whole exception info is present there to let you know that your logic in the router has failed: you probably didn't expect that No channel resolved by router 'recursaoRendaVariavel' for your use-case.
From here, if you really think that your flow is doing OK failing over to the next subscriber for that router error, then you just can ignore such an INFO message in the logs or turn off INFO for org.springframework.integration at all.

Related

Spring Integration: can one call a gateway from within a header enricher?

I need to make a number of calls to gateways and to then place the return payloads into headers. These gateway calls are really sending a message to a channel behind which there is a chain. It currently looks like this:
<int:channel id = "call_api_a" />
<int:chain input-channel = "call_api_a" >
...
</int:chain>
<int:channel id = "call_api_b" />
<int:chain input-channel = "call_api_b" >
...
</int:chain>
<int:gateway request-channel="call_api_a" />
<int:header-enricher>
<int:header name="a" expression="payload" />
</int:header-enricher>
<int:gateway request-channel="call_api_b" />
<int:header-enricher>
<int:header name="b" expression="payload" />
</int:header-enricher>
Is there an elegant way to embed the call to the gateway inside of the header-enricher?
Something like:
<int:header-enricher>
<int:header name="a">
<int:gateway request-channel="call_api_a" />
</int:header>
</int:header-enricher>
I know that the above doesn't work but gives the sense of what I'd like to achieve.
Thanks for any pointers and best regards.
-aljo
Not <gateway>, but like this:
<int:header-enricher>
<int:header name="a" ref="myGateway" method="gatewayMethod"/>
</int:header-enricher>
The <gateway> is bean based on some service interface.
You just point in the <header> definition to that bean and its method to be called against your payload or message.
There is some explanation in the docs: https://docs.spring.io/spring-integration/docs/current/reference/html/message-transformation.html#header-enricher
It looks like the "additional gateway definition" is the way to go on this one. Thanks, #artem-bilan, for pointing me in the right direction.
I want to call to my chain-channel directly from a header-enricher.
If my chain-channel is:
<int:channel id = "call_api_a" />
<int:chain input-channel = "call_api_a" >
...
</int:chain>
Define somewhere in the Java add your gateway interface.
package com.app.wonderful;
#FunctionalInterface
public interface MyChainChannelGatewayMethod {
Message<?> callChainChannel(Message<?> message) throws MessageException;
}
Define a gateway that points to your chain-channel:
<int:gateway default-request-channel = "call_api_a"
id = "call_api_a_GW"
service-interface. = "com.app.wonderful.MyChainChannelGatewayMethod" />
Then you can call your gateway in-line from the SpEL expression in the header-enricher:
<int:header-enricher >
<int:header name="a" expression="#call_api_a_GW(#root).payload" />
</int:header>
Does the trick for me. Thanks again.
#artem-bilan's suggestion to use <enricher> instead of <header-enricher> leads to a solution that obviates the Java interface signatures by addressing directly a channel.
<int:channel id = "call_api_a" />
<int:chain input-channel = "call_api_a" >
...
</int:chain>
We can call this channel from an <enricher>. Here, for simplicity, the <enricher> component is part of a chain, but that is not a requirement:
<int:chain ...>
<int:enricher request-channel="call_api_a"
request-payload-expression="payload" >
<int:header name="a" expression="payload" />
</int:enricher>
</int:chain>
Thanks again for the pointers.

Send and receive data using Spring Integration TCP IP socket

I am creating a simple spring boot application(PoC) to send product id's (string) from client to server over socket using Spring integration TCP. If the server is hit with correct product data, the server will respond back with the product details which I need to print. Just need to establish a connection and get the response by sending proper data.
Please tell me what are the classes I am supposed to implement? outbound/inboud gateways,messsage channels, tcplisteners? Should I go with xml configuration or annotations? I am new to SI and would be of great help if you could give me an idea on how to implement it.
Here is my updated integration xml.
<int-ip:tcp-connection-factory id="client" type="client" host="XX.XX.XX.99" port="9XXX" single-use="true" so-timeout="10000" />
<int:channel id="input"/>
<int-ip:tcp-outbound-gateway id="outGateway" request-channel="input" reply-channel="clientBytes2StringChannel" connection-factory="client" request-timeout="10000" reply-timeout="10000"/>
<int:object-to-string-transformer id="clientBytes2String" input-channel="clientBytes2StringChannel"/>
<int:service-activator input-channel="clientBytes2StringChannel" ref="echoService" method="test"/>
<bean id="echoService" class="org.springframework.integration.samples.tcpclientserver.EchoService"/>
<int:channel id="toSA"/>
But this still prints the echoed result. Also, when I call getHost on abstractClientConnectionfactory from main class, its showing "localhost". How can I confirm if the connection is active?
<int:gateway id="gw"
service-interface="org.springframework.integration.samples.tcpclientserver.SimpleGateway"
default-request-channel="input"/>
<int-ip:tcp-connection-factory id="client" type="client" host="xx.xx.xx.99"
port="9xxx"
single-use="false" so-timeout="300000" using-nio="false"
so-keep-alive="true" serializer="byteArrayRawSerializer"
deserializer="byteArrayRawSerializer"/>
<bean id="byteArrayRawSerializer" class="org.springframework.integration.ip.tcp.serializer.ByteArrayRawSerializer" />
<int-ip:tcp-outbound-gateway id="outGateway"
request-channel="input"
reply-channel="responseBytes2StringChannel"
connection-factory="client"
request-timeout="10000"
reply-timeout="10000" />
<int:object-to-string-transformer id="clientBytes2String"
input-channel="responseBytes2StringChannel" output-channel="toSA"/>
<int:service-activator input-channel="toSA" ref="echoService" method="test"/>
<bean id="echoService" class="org.springframework.integration.samples.tcpclientserver.EchoService"/>
<int:channel id="toSA"/>
<int:transformer id="errorHandler" input-channel="errorChannel" expression="payload.failedMessage.payload + ':' + payload.cause.message"/>
<int:channel id="responseBytes2StringChannel"></int:channel>
**** Update SI xml ****
<int:gateway id="gw"
service-interface="org.springframework.integration.samples.tcpclientserver.SimpleGateway"
default-request-channel="objectIn"/>
<int:channel id="objectIn" />
<int-ip:tcp-connection-factory id="client"
type="client"
host="xx.xx.xx.99"
port="9xxx"
single-use="true"
so-timeout="50000"
using-nio="false"
so-keep-alive="true"/>
<!--
serializer="byteArrayLengthSerializer"
deserializer="byteArrayLengthSerializer"
<bean id="byteArrayLengthSerializer" class="org.springframework.integration.ip.tcp.serializer.ByteArrayLengthHeaderSerializer " />
-->
<int:payload-serializing-transformer input-channel="objectIn" output-channel="objectOut"/>
<int-ip:tcp-outbound-gateway id="outGateway"
request-channel="objectOut"
reply-channel="bytesIn"
connection-factory="client"
request-timeout="10000"
reply-timeout="10000"
/>
<int:payload-deserializing-transformer input-channel="bytesIn" output-channel="objectOut" />
<int:object-to-string-transformer id="clientBytes2String"
input-channel="objectOut" output-channel="toSA"/>
<int:service-activator input-channel="toSA" ref="echoService" method="test"/>
<bean id="echoService" class="org.springframework.integration.samples.tcpclientserver.EchoService"/>
<int:channel id="objectOut"/>
<int:channel id="toSA"/>
<int:channel id="bytesIn"/>
I suggest you to go the Documentation route first: https://docs.spring.io/spring-integration/docs/current/reference/html/ip.html to investigate what Spring Integration provides for you in regards of TCP/IP. Then it would be great to jump into samples project to see what we suggest for configuration and usage options: https://github.com/spring-projects/spring-integration-samples

How to log request data along with response data in http:outbound-gateway

Using spring integration, I am reading from a queue and then calling a REST service using http:outbound-gateway. The code works fine. But I want to relate the logs such that for a given request key field , so and so response is received. Otherwise, it is very difficult to pinpoint for which request the response is received, when there are thousands of messages flowing through the queue.
My JSON request for the service call is as follows:
{"ID":"123","status":"A"}
my JSON Response from the service call is as follows:
{"transactionStatus":"Success"}
I want to do logging such that "ID:123" has got a reponse transactionStatus as "Success".
Please help me with the code how I can achieve this. Please let me know if you need further details.
Thanks in advance.
<int:object-to-json-transformer input-channel = "gcmRequestChannel" output-channel="RESTSrvcChannel"></int:object-to-json-transformer>
<int:header-enricher id = "restenricher" input-channel = "RESTSrvcChannel" output-channel = "RESTSrvcChannel2">
<int:header name="contentType" value="application/json"/>
<int:header name="SPApikey" value="${throttler.SPApikey}" />
</int:header-enricher>
<http:outbound-gateway id="gcmrestHttpOutboundGateway" request-channel="RESTSrvcChannel2" reply-channel="nullChannel"
extract-request-payload="true"
url="${throttler.url}"
header-mapper="headerMapper"
http-method="POST"
expected-response-type="java.lang.String"
>
</http:outbound-gateway>
<beans:bean id="headerMapper"
class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
<beans:property name="inboundHeaderNames" value="*" />
<beans:property name="outboundHeaderNames" value="HTTP_REQUEST_HEADERS,SPApikey" />
<beans:property name="userDefinedHeaderPrefix" value="" />
</beans:bean>
Since Spring Integration deals with the Message object in its components and via channels in between, there is a nice solution like supply your important information into the headers and they will be available in the replyMessage for your logging purpose:
<header-enricher>
<header name="originalPayload" expression="payload"/>
</header-enricher>
I have coded as suggested by you. Thanks for your response.
<int:header-enricher id = "gcmrestenricher" input-channel = "gcmRESTSrvcChannel" output-channel = "gcmRESTSrvcChannel2">
<int:header name="contentType" value="application/json"/>
<int:header name="SPApikey" value="${throttler.SPApikey}" />
<int:header name="JSONPayload" expression="payload"/>
</int:header-enricher>
<http:outbound-gateway id="gcmrestHttpOutboundGateway" request-channel="gcmRESTSrvcChannel2" reply-channel="gcmRESTSrvcOutputChannel"
extract-request-payload="true"
url="${throttler.gcmurl}"
header-mapper="gcmheaderMapper"
http-method="POST"
expected-response-type="java.lang.String"
>
</http:outbound-gateway>
<beans:bean id="gcmheaderMapper"
class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
<beans:property name="inboundHeaderNames" value="*" />
<beans:property name="outboundHeaderNames" value="HTTP_REQUEST_HEADERS,SPApikey,JSONPayload" />
<beans:property name="userDefinedHeaderPrefix" value="" />
</beans:bean>
<beans:bean id="logmsg" class = "com.MLAServiceActivator"></beans:bean>
<int:service-activator requires-reply="false" input-channel="gcmRESTSrvcOutputChannel" ref="logmsg" method="ResponseLogging"></int:service-activator>
#ServiceActivator
public void ResponseLogging(Message<String> message)
{
logger.info("The response message is:"+message.getPayload()+ " for request message:"+message.getHeaders().get("JSONPayload"));
}

spring integration tcp server send message to tcp client

I want to write a perfect client-server application is Spring Integration. I have a part where server receive a message and send response to client.
I would like to send to client a message with some information from time to time also. I set a header with connectionId received in TcpConnectionEvent but there is nothing happend. There is my code bellow. I stack with this problem from few days. Thanks for any halp!
<!-- CLIENT SIDE -->
<int:gateway id="gw"
service-interface="com.app.hos.service.client.Gateway"
default-request-channel="input"/>
<int-ip:tcp-connection-factory id="client"
type="client"
host="localhost"
port="14020"
single-use="false"
so-timeout="10000"
/>
<int:channel id="input" />
<int-ip:tcp-outbound-gateway id="outGateway"
request-channel="transformChannel"
reply-channel="reply"
connection-factory="client"
request-timeout="10000"
reply-timeout="10000"
/>
<int:channel id="transformChannel" />
<int:channel id="reply" datatype="java.lang.String" />
<!-- TRANSFORMERS -->
<int:transformer id="testTransformer" ref="testTransformerBean" input-channel="input"
method="transform" output-channel="transformChannel"/>
<bean id="testTransformerBean" class="com.app.hos.service.integration.Transformer" />
<!-- SERVER SIDE -->
<bean id="connectionSerializeDeserialize" class="com.app.hos.service.integration.ByteArrayToStringConverter"/>
<int-ip:tcp-connection-factory id="hosServer"
type="server"
port="14020"
serializer="connectionSerializeDeserialize"
deserializer="connectionSerializeDeserialize"
using-nio="true"/>
<int-ip:tcp-inbound-gateway id="inputHosGateway"
connection-factory="hosServer"
request-channel="toServerChannel"
error-channel="errorChannel"/>
<int:channel id="toServerChannel"/>
<int:channel id="errorChannel"/>
<int:channel id="inputChannel" />
<int:service-activator input-channel="toServerChannel"
ref="server"
method="serverTest"/>
<bean id="server"
class="com.app.hos.service.server.Server" />
<!-- TCP EVENTS -->
<int:service-activator input-channel="eventChannel"
ref="event"
method="eventTest"/>
<bean id="event"
class="com.app.hos.service.integration.Event" />
<int:channel id="eventChannel"/>
<int-event:inbound-channel-adapter channel="eventChannel"
event-types="org.springframework.integration.ip.tcp.connection.TcpConnectionEvent"/>
Transforemr where I set connectionId:
#Autowired
public Event event;
public Message<String> transform(Message<String> msg) {
Message<String> newMessage = MessageBuilder.withPayload(msg.getPayload())
.setHeader(IpHeaders.CONNECTION_ID, event.getConncetionId())
.copyHeadersIfAbsent(msg.getHeaders())
.build();
return newMessage;
}
MVC Controller where I try send a message by a gateway:
#Autowired
public TestController(Gateway gateway) {
this.gateway = gateway;
}
#RequestMapping(value = "/showTest", method=RequestMethod.GET)
public String showTestPage() {
return "test/sendMessageTest";
}
#RequestMapping(value = "/sendMessage", method=RequestMethod.GET)
public void sendMessage() {
gateway.send("Working!");
}
You can't use gateways when sending arbitrary data they are strictly for request/reply messaging.
In any case, you are sending to a completely different connection.
Instead of an inbound gateway, you need an inbound channel adapter and outbound channel adapter (sharing the server connection factory).
When you want to send arbitrary data (not part of a request/reply), send the message to the oubound channel adapter, with the connection id header set appropriately.
Thanks for help! That's the solution:
<int:channel id="input" />
<int-ip:tcp-outbound-channel-adapter id="outboundChannel"
channel="transformChannel"
connection-factory="hosServer" />
<int-ip:tcp-inbound-channel-adapter id="inboundChannel"
channel="toServerChannel"
connection-factory="hosServer"
/>
<int:channel id="transformChannel" />
<int:channel id="reply" datatype="java.lang.String" />
<!-- TRANSFORMERS -->
<int:transformer id="testTransformer" ref="testTransformerBean" input-channel="input"
method="transform" output-channel="transformChannel"/>
<bean id="testTransformerBean" class="com.app.hos.service.integration.Transformer" />
<!-- SERVER SIDE -->
<bean id="connectionSerializeDeserialize" class="com.app.hos.service.integration.ByteArrayToStringConverter"/>
<int-ip:tcp-connection-factory id="hosServer"
type="server"
port="14020"
serializer="connectionSerializeDeserialize"
deserializer="connectionSerializeDeserialize"
using-nio="true"/>
<int:channel id="toServerChannel"/>
<int:channel id="errorChannel"/>
<int:channel id="inputChannel" />
<int:service-activator input-channel="toServerChannel"
ref="server"
method="serverTest"/>
<bean id="server"
class="com.app.hos.service.server.Server" />
<!-- TCP EVENTS -->
<int:service-activator input-channel="eventChannel"
ref="event"
method="eventTest"/>
<bean id="event"
class="com.app.hos.service.integration.Event" />
<int:channel id="eventChannel"/>
<int-event:inbound-channel-adapter channel="eventChannel"
event-types="org.springframework.integration.ip.tcp.connection.TcpConnectionEvent"/>

Unable to route to Message endpoints using SpEL in spring router

I have a message-driven-channel-adapter which is listening to a jms queue 'inputqueue' to which an application is posting a json message in the below format.
{
"name": "Praveep",
"action": "Drink",
"age": "32",
"userid": "pk",
"details": [{
"state": "karnataka",
"country": "India",
}]
}
Inside my applicationContext file I have defined a router which based on the action will point the message to the appropriate queue.
<int:channel id="processEmpChannel">
<int:queue />
</int:channel>
<int:channel id="drink">
<int:queue />
</int:channel>
<int:channel id="eat">
<int:queue />
</int:channel>
<int:channel id="sleep">
<int:queue />
</int:channel>
<int:router input-channel="processEmpChannel" expression="$.action">
<int:mapping value="drink" channel="drink" />
<int:mapping value="eat" channel="eat" />
<int:mapping value="sleep" channel="sleep" />
</int:router>
<int:service-activator input-channel="drink"
ref="springExample" method="handleDrink">
<int:poller ref="poller"></int:poller>
</int:service-activator>
<int:service-activator input-channel="eat"
ref="springExample" method="handleEat">
<int:poller ref="poller"></int:poller>
</int:service-activator>
<int:service-activator input-channel="sleep"
ref="springExample" method="handleSleep">
<int:poller ref="poller"></int:poller>
</int:service-activator>
In my Class file I have defined methods for each of the actions inside a public method. When I run the java program, I am getting the below error. Can someone let me know where I am going wrong in the spel expression.
Property or field '$' cannot be found on object of type 'org.springframework.messaging.support.GenericMessage' - maybe not public?
The JSON property accessor is not configured by default, add:
<int:spel-property-accessors>
<bean id="jsonPropertyAccessor" class="org.springframework.integration.json.JsonPropertyAccessor"/>
</int:spel-property-accessors>

Resources