I have a producers( write in CPP) that send to “spring-integration server” the binary-data.
And it works correctly as :
spring integration time out clients
Now I have to send a reply (like an ACK) to the producer.
I have read about the gateway, but actually I’m confused.
My configuration is:
<int-ip:tcp-connection-factory id="serverTcpConFact"
type="server"
port="5566"
using-nio="true"
single-use="false"
task-executor="myTaskExecutor"
deserializer="serializer"
serializer="serializer"/>
<int-ip:tcp-inbound-channel-adapter id="tcpInboundAdapter"
channel="tcpInbound"
connection-factory="serverTcpConFact" />
<int:channel id="tcpInbound" />
<int:service-activator
output-channel="tcpOutbound"
input-channel="tcpInbound"
ref="importService"
method="handler" />
<bean id="importService" class="my.ImportService" />
<int:channel id="tcpOutbound" />
<int:gateway id="mygateway"
service-interface="my.IpMyGatway"
default-request-channel="tcpInbound"
default-reply-channel="tcpOutbound"
default-reply-timeout="6000"/>
I also have an custom serializator, the problem is that the my spring integration server doesn’t send the reply.
I need that the reply executes:
#Override
public void serialize(MyMessage arg0, OutputStream outputStream) throws IOException {
// TODO Auto-generated method stub
logger.info("serialize messages");
// here I have to write my ACK ! ( .. or not?)
}
And then sends the message to the producer for each message.
Thank you.
I wonder why <int-ip:tcp-inbound-gateway> isn't enough for you...
There is just enough to generate a reply message from service and gateway will send it ot the client as response.
The simple sample:
<ip:tcp-inbound-gateway id="gatewaySerializedNio"
connection-factory="connectionFactory"
request-channel="serviceChannel" />
<channel id="serviceChannel" />
<service-activator input-channel="serviceChannel"
ref="service" method="process"/>
<beans:bean id="service" class="com.my.proj.MyService" />
The return value from MyService#process method will be serialized to the TCP socket.
Related
So I have application that sends message to activemq queue with spring integration.
<int-feed:inbound-channel-adapter id="feedAdapter"
channel="feedChannel"
auto-startup="${auto.startup:true}"
url="https://stackoverflow.com/feeds/question/49479712">
<int:poller fixed-rate="10000"/>
</int-feed:inbound-channel-adapter>
<int:channel id="feedChannel"/>
<int:transformer id="transformer" input-channel="feedChannel"
expression="payload.title + payload.author + '#{systemProperties['line.separator']}'"
output-channel="feedOutputChannel"/>
<int:channel id="feedOutputChannel"/>
<jms:outbound-gateway id="jmsOutGateway"
request-destination="inputQueue"
request-channel="feedOutputChannel"
requires-reply="false"/>
But now I want to create different application which consumes message from that queue and just prints it out to console with spring integration. I have made this:
<jms:message-driven-channel-adapter id="JMSInboundAdapter" destination="inputQueue"/>
<bean id="inputQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="input.queue"/>
</bean>
It works when I run application that sends message to queue. But it doesnt when I run message consume application.
Error I get : Dispatcher has no subscribers for channel 'application.JMSInboundAdapter'.
How do I need to configure my message consumer application?
If there is no channel on the adapter, the id becomes the channel name.
You need something to subscribe to that channel (e.g. a <service-activator inputChannel="JMSInboundAdapter" ... />).
I'm new in Spring Integration and I'm working with two process:
1.- Read files from sftp, save information. I use method "mget".
2.- After of save information, rename files processed in sftp server with method "mput".
this is my configuration:
<bean id="filePrinter" class="com.maven.integration.FilePrinter" />
<int:channel id="outboundChannel"></int:channel>
<int:channel id="aggregateResultsChannel"/>
<int:channel id="toGet"></int:channel>
<int:gateway id="simpleGateway" service-interface="com.maven.integration.FileGateway"
default-request-channel="ftpChannel" />
<int-sftp:outbound-gateway
session-factory="sftpClientFactory"
request-channel="ftpChannel"
command="mget"
command-options="-R -P"
expression="payload"
filename-regex="(new|.*.csv)"
mode="IGNORE"
local-directory-expression="#targetDir.get() + #remoteDirectory"
reply-channel="outboundChannel"
>
<int-sftp:request-handler-advice-chain>
<int:retry-advice />
</int-sftp:request-handler-advice-chain>
</int-sftp:outbound-gateway>
<int:splitter input-channel="outboundChannel" output-channel="toGet"/>
<bean id="targetDir" class="java.util.concurrent.atomic.AtomicReference">
<constructor-arg value="${target}"/>
</bean>
<int:service-activator ref="filePrinter" method="print"
input-channel="toGet"/>
<int-sftp:outbound-gateway
session-factory="sftpClientFactory"
request-channel="toGet"
command="mput"
command-options="-R"
local-directory="src/test/"
expression="payload"
filename-regex="(new|.*.csv)"
mode="IGNORE"
remote-filename-generator-expression="payload.getName() + '.ack'"
remote-directory-expression="#remoteDirectory"
reply-channel="aggregateResultsChannel"
>
<int-sftp:request-handler-advice-chain>
<int:retry-advice />
</int-sftp:request-handler-advice-chain>
</int-sftp:outbound-gateway>
<int:aggregator input-channel="aggregateResultsChannel"/>
currently only the first outbound-gateway with mget command is executed, but the second outbound-gateway is not executed, how could the second process run?
Because your toGet is a simple DirectChannel with the "only one per message subscriber" logic. At the same time your mput gateway uses that as its request-channel="toGet" sharing this channel with the
<int:service-activator>. And since this is earlier in the config, it is a first subscriber in thetoGetand therefore only this one process the message sent to thetoGet` by the splitter.
I think what you need to do (if the story is still about mput) is exactly opposite with what you have in mget. So, you should do that logic alongside with the splitting, not after. Therefore you should send MGET result to the splitter and to the MPUT in parallel. For this purpose I suggest you to change your outboundChannel to the <publish-subscribe-channel> and use this outboundChannel in the mput gateway for its request-channel.
I have created bean for inbound channel with acknowledge property as manual, and chain method for publishing the output message ,
<int-amqp:inbound-channel-adapter channel="InputChannel"
queue-names="Input" connection-factory="connectionFactory" concurrent-consumers="1" message-converter="Converter"
acknowledge-mode="MANUAL" prefetch-count="5"/>
<int:chain input-channel="InputChannel" output-channel="OutputChannel">
<int:transformer method = "transform" >
<bean class="com.sampleconverter" />
</int:transformer>
<int:service-activator method="transform">
<bean class="com.Transformer" />
</int:service-activator>
<int:object-to-string-transformer />
</int:chain>
Can you please help me with the way to acknowledge messages processed with the manual acknowledge mode,
Thanks in advance.
The Reference Manual has dedicated paragraph on the matter:
Setting the mode toMANUAL allows user code to ack the message at some other point during processing. To support this, with this mode, the endpoints provide the Channel and deliveryTag in the amqp_channel and amqp_deliveryTag headers respectively.
#ServiceActivator(inputChannel = "foo", outputChannel = "bar")
public Object handle(#Payload String payload, #Header(AmqpHeaders.CHANNEL) Channel channel,
#Header(AmqpHeaders.DELIVERY_TAG) Long deliveryTag) throws Exception {
// Do some processing
if (allOK) {
channel.basicAck(deliveryTag, false);
// perhaps do some more processing
}
else {
channel.basicNack(deliveryTag, false, true);
}
return someResultForDownStreamProcessing;
}
I have an inbound RabbitMQ channel adapter that successfully processes 3000 messages per day, however very occasionally I see a unacked message count of 1 in the RabbitMQ admin console. This seems to remain like that.
I do have a re-try advice chain to re-try 3 times and then move to a DLQ via a dead letter routing key, this has worked fine for most exceptions.
The unacked has happened twice in the last few weeks, and on one of the occasions I was able to take a thread dump and see that the int-http:outbound-gateway call was stuck waiting for a http response getStatusCode()
I have a receive-timeout="59000" on the int-amqp:inbound-channel-adapter which I was hoping would timeout the thread anywhere it exceeds the timeout ?
I now notice there is a reply-timeout attribute on the int-http:outbound-gateway should I be setting that ?
Any ideas appreciated ?
<int-amqp:inbound-channel-adapter id="amqpInCdbEvents" channel="eventsAMQPChannel" channel-transacted="true" transaction-manager="transactionManager"
queue-names="internal.events.queue" connection-factory="connectionFactory"
receive-timeout="59000" concurrent-consumers="${eventsAMQPChannel.concurrent-consumers}"
advice-chain="retryChain" auto-startup="false" />
<int:channel id="eventsAMQPChannel" />
<!-- CHAIN of processing for Asynch Processing of Events from intermediate Queue -->
<int:chain id="routeEventChain" input-channel="eventsAMQPChannel">
<int:json-to-object-transformer type="xx.xx.xx.json.Event" object-mapper="springJacksonObjectMapper"/>
<int:header-enricher>
<int:header name="originalPayload" expression="payload" overwrite="true"/>
<int:header name="message_id" expression="payload.id" overwrite="true"/>
</int:header-enricher>
<int:router expression="payload.eventType">
<int:mapping value="VALUE" channel="valueEventChannel"/>
<int:mapping value="SWAP" channel="swapEventChannel"/>
</int:router>
</int:chain>
<int:channel id="valueEventChannel" />
<int:channel id="swapEventChannel" />
<int:chain id="valueEventChain" input-channel="valueEventChannel" output-channel="nullChannel">
<int:transformer ref="syncValuationTransformer" />
<int:object-to-json-transformer object-mapper="springJacksonObjectMapper" />
<int:header-enricher>
<int:header name="contentType" value="application/json;charset=UTF-8" overwrite="true"/>
</int:header-enricher>
<int-http:outbound-gateway id="httpOutboundGatewayValuationServiceFinalValuation"
expected-response-type="java.lang.String"
http-method="POST" charset="UTF-8"
extract-request-payload="true"
url="${value.service.uri}/value"/>
</int:chain>
reply-timeout is a timeout when sending the reply to the reply channel (if it can block - e.g. a bounded queue channel that's full).
int-http:outbound-gateway call was stuck waiting for a http response getStatusCode()
You set the client timeout (readtimeout) on a ClientHttpRequestFactory that you can configure into the outbound adapter...
/**
* Create a new instance of the {#link RestTemplate} based on the given {#link ClientHttpRequestFactory}.
* #param requestFactory HTTP request factory to use
* #see org.springframework.http.client.SimpleClientHttpRequestFactory
* #see org.springframework.http.client.HttpComponentsClientHttpRequestFactory
*/
public RestTemplate(ClientHttpRequestFactory requestFactory) {
this();
setRequestFactory(requestFactory);
}
I am using spring integration to make a client socket (java code), which must send messages to server socket (flash client). Basically, i want to push messages to flash through socket communication without caring for any response from it. The message which should be sent is coming from GW upon send method is called.
I am able to push a message, but the problem is that my client socket is waiting for a response and if it doesn't get one it times out at some point. Here is my configuration:
<int:gateway id="gw"
service-interface="integration.MessageGateway"
default-request-channel="input"/>
<int-ip:tcp-connection-factory id="client"
type="client"
host="localhost"
port="6767"
serializer="clientSerializer"
single-use="true" so-keep-alive="true"
so-timeout="10000"/>
<bean id="clientSerializer" class="org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer" />
<int:channel id="input" />
<int-ip:tcp-outbound-gateway id="outGateway"
request-channel="input"
connection-factory="client"
request-timeout="10000"
reply-timeout="10000"/>
Consider to use one-way <int-ip:tcp-outbound-channel-adapter>: http://docs.spring.io/spring-integration/docs/latest-ga/reference/html/ip.html#tcp-adapters