firstly thanks for attention
i define outbound-gateway ftp adapter to run ftp command on target server,my goal is run periodically ls,mv,get,... commands on server and run task on batch library job, my code is:
<bean id="ftpClientFactory1" class="org.springframework.integration.ftp.session.DefaultFtpSessionFactory">
<property name="host" value="127.0.0.1"/>
<property name="port" value="21"/>
<property name="username" value="banks_reader"/>
<property name="password" value="123456"/>
<property name="clientMode" value="2"/>
<property name="fileType" value="2"/>
</bean>
<int:gateway id="gw" service-interface="ir.ali.util.ToFtpFlowGateway"
default-request-channel="inbound1"/>
<int:channel id="inbound1"/>
<int-ftp:outbound-gateway id="gateway1"
session-factory="ftpClientFactory1"
request-channel="inbound1"
reply-channel="outbound"
reply-timeout="777"
auto-create-local-directory="false"
auto-startup="true"
filename-pattern="*"
remote-file-separator="/"
command="ls"
command-options="-dirs -R"
expression="payload"
mput-regex=".*"
>
</int-ftp:outbound-gateway>
<int:channel id="outbound">
<int:interceptors>
<int:wire-tap channel="logger"/>
</int:interceptors>
</int:channel>
<int:channel id="outboundJobRequestChannel"/>
<int:logging-channel-adapter id="logger" log-full-message="true" />
<int:transformer input-channel="outbound" output-channel="outboundJobRequestChannel">
<bean class="ir.ali.configuration.FileMessageToJobRequest"/>
</int:transformer>
<int:splitter id="splitter" input-channel="outbound" output-channel="ftpChannel"/>
<int:channel id="ftpChannel">
<int:queue/>
</int:channel>
and in Application Class send message to inbound1 channel and start int-ftp:outbound-gateway the code is:
final ToFtpFlowGateway toFtpFlow = ctx.getBean(ToFtpFlowGateway.class);
try {
List<Boolean> rmResults = toFtpFlow.lsGetAndRmFiles("/");
} catch (Exception e) {
e.printStackTrace();
}
it's worked correctly , the problem is that i needed run periodically ls and mv ,... recursive command on the server,how to run toFtpFlow.lsGetAndRmFiles("/"); periodically to start int-ftp:outbound-gateway ?
<int:inbound-channel-adapter expression="/" channel="inbound1">
<int:poller fixed=delay="60000" />
</int:inbound-channel-adapter>
<int:channel id="inbound1"/>
<int-ftp:outbound-gateway id="gateway1"
session-factory="ftpClientFactory1"
request-channel="inbound1"
reply-channel="outbound"
reply-timeout="777"
auto-create-local-directory="false"
auto-startup="true"
filename-pattern="*"
remote-file-separator="/"
command="ls"
command-options="-dirs -R"
expression="payload"
mput-regex=".*"/>
Related
How to use the RedeliveryPolicy in case of failed messages in outbound->inbound->httpoutboundgateway(messages failing here)->external service
the failed messages are not getting retried based on the RedeliveryPolicy mainly because the message is already dequeued before the exception occurs.
<int:channel id="jmsOutChannel" />
<jms:outbound-channel-adapter id="outboundJMSAdaptor" jms-template="jmsTemplate"
channel="jmsOutChannel"
destination-name="#{somebean.queueName}"/>
<int:channel id="jmsInChannel" />
<jms:message-driven-channel-adapter
channel="jmsInChannel" destination-name="#{somebean.queueName}"
connection-factory="jmsConnectionFactory" message-converter="jmsMessageConverter"/>
<int:header-enricher input-channel="jmsInChannel" output-channel="outbound_gateway_channel">
<int:header name="addressId" expression="payload.getId()"/>
<int:header name="Accept-Language" value="en_GB"/>
<int:header name="X-Source-CountryCode" value="GB"/>
<int:header name="X-Source-Operator" value="Enterprise"/>
<int:header name="X-Source-Division" value="CustomerManagement"/>
<int:header name="X-Source-System" value="${sapwebservices.http.header.source.system}"/>
<int:header name="X-Source-Timestamp" expression="new java.text.SimpleDateFormat('yyyy-MM-dd HH:mm:ss').format(new java.util.Date())"/>
<int:header name="Accept" value="application/json"/>
<int:header name="Content-Type" value="application/json;charset=UTF-8"/>
</int:header-enricher>
<bean id="httpRequestFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<property name="connectTimeout" value="${sapwebservices.http.rest.timeout}"/>
<property name="readTimeout" value="${sapwebservices.http.rest.timeout}"/>
<property name="httpClient" ref="httpClient"/>
</bean>
<int:object-to-json-transformer input-channel="outbound_gateway_channel"
output-channel="outbound_gateway_with_json"
object-mapper="nonNullObjectMapper"/>
<http:outbound-gateway mapped-request-headers="Accept*, Content-Type, X-*, HTTP_REQUEST_HEADERS"
request-channel="outbound_gateway_with_json"
reply-channel="print_payload"
url="${sapwebservices.ws.uri.updatecustomershippingaddress}"
http-method="PUT"
expected-response-type="java.lang.String"
charset="UTF-8"
request-factory="httpRequestFactory">
<http:uri-variable name="id" expression="headers['addressId']"/>
</http:outbound-gateway>
And for the redelivery policy I have,
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="messageConverter" ref="jmsMessageConverter" />
<property name="connectionFactory">
<bean class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory">
<ref local="jmsConnectionFactory" />
</property>
</bean>
</property>
</bean>
<bean id="jmsConnectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
<property name="userName" value="admin"/>
<property name="password" value="admin"/>
<property name="redeliveryPolicy" ref="redeliveryPolicy"/>
<property name="nonBlockingRedelivery" value="true"/>
</bean>
<bean id="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<property name="maximumRedeliveries" value="${sapwebservice.redeliveryPolicy.maximumRedeliveries}"/>
<property name="initialRedeliveryDelay" value="${sapwebservice.redeliveryPolicy.initialRedeliveryDelay}"/>
<property name="backOffMultiplier" value="${sapwebservice.redeliveryPolicy.backOffMultiplier}"/>
<property name="useExponentialBackOff" value="${sapwebservice.redeliveryPolicy.useExponentialBackOff}"/>
<property name="redeliveryDelay" value="${sapwebservice.redeliveryPolicy.redeliveryDelay}"/>
</bean>
<bean id="demoQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="demo.queue"/>
</bean>
<bean id="jmsMessageConverter" class="sap.converter.JMSMessageConverter"/>
<amq:broker useJmx="true" persistent="false">
<amq:destinationPolicy>
<amq:policyMap>
<amq:defaultEntry>
<amq:policyEntry queue=">">
<amq:deadLetterStrategy>
<amq:individualDeadLetterStrategy queuePrefix="dlq." useQueueForQueueMessages="true"/>
</amq:deadLetterStrategy>
</amq:policyEntry>
</amq:defaultEntry>
</amq:policyMap>
</amq:destinationPolicy>
<amq:transportConnectors>
<amq:transportConnector uri="tcp://localhost:0" />
</amq:transportConnectors>
</amq:broker>
Expected result is to retry based in the RedeliveryPolicy and finally end up in dlq if all the retrials are failed.
Set acknowledge="transacted" on the message-driven channel adapter.
Spring Integration versions 4.2 and later (the current version is 5.1.7) set it to that by default; for earlier versions you have to set it in your configuration so the flow runs in a transaction and the dequeue is rolled back after an exception is thrown.
<bean id="triggerFileScanner" class="abc.xyz">
<property name="triggerFile" value="value1" />
</bean>
<int-file:inbound-channel-adapter id="fileInbound" directory="somepath/directory" filter="acceptallFilter" scanner="triggerFileScanner"
auto-startup="true" channel="fileChannel">
<int:poller max-messages-per-poll="10" time-unit="SECONDS" fixed-delay="10" receive-timeout="30000" />
</int-file:inbound-channel-adapter>
<int:header-enricher id="headerEnricher" input-channel="fileChannel" output-channel="processChannel">
<int:header name="flowName" value="Name" />
<int:header name="flowID" method="uuidgenerate" ref="headerEnricherBean" />
<int:header name="flowStartTime" method="generateTimeString" ref="headerEnricherBean"></int:header>
<int:header name="fileName" method="deriveFileName" ref="headerEnricherBean" />
</int:header-enricher>
<int:channel id="processChannel">
<int:interceptors>
<int:wire-tap channel="copyChannel" id="copyTap" />
</int:interceptors>
</int:channel>
<int:channel id="copyChannel"></int:channel>
<int-file:outbound-channel-adapter id="fileCopier" channel="copyChannel" delete-source-files="false" filename-generator="dateSuffixFileNameGenerator"
directory="copy.path">
</int-file:outbound-channel-adapter>
<int:filter id="formatcheckFilter" ref="formatValidator" method="validateFile" input-channel="processChannel" output-channel="processDataChannel"
discard-channel="errorChannel" auto-startup="true">
</int:filter>
<int:service-activator id="converter" input-channel="processDataChannel" method="convert" ref="fileToQueryConverter" auto-startup="true"
output-channel="impChannel" />
<bean id="importer" class="testbean.import">
<property name="errorpath" value="path1" />
<property name="sourcepath" value="path2" />
</bean>
<int:service-activator input-channel="impChannel" ref="impeximporter" id="importProcess" method="import" auto-startup="true"
output-channel="archiveChannel" />
<int:channel id="archiveChannel">
<int:interceptors>
<int:wire-tap channel="logChannel" id="completionLogger" />
</int:interceptors>
</int:channel>
<int:channel id="logChannel"></int:channel>
<int-file:outbound-channel-adapter id="fileArchiver" channel="archiveChannel" delete-source-files="true" filename-generator="dateSuffixFileNameGenerator"
directory="archive.path">
</int-file:outbound-channel-adapter>
<int:service-activator id="flowLogger" input-channel="logChannel" ref="messageLogger" method="logMessage">
</int:service-activator>
Sometimes the exceptions from service activator are going to the error channel, however some times they are not going.
I have the error channel defined as below:
<int:channel id="errorChannel" />
<bean id="exceptionHandler" class=my.custom.ExceptionHandler">
</bean>
<int:service-activator id="errorLogger" input-channel="errorChannel" method="handle" ref="exceptionHandler">
</int:service-activator>
I have this error channel being used in many integrations and in my service activators i am just doing a throw Exception("Message")
I'm using
Spring Batch
Step 1
Step 2 Master (Partitioner)
Step 3
Spring Integration (JMS) to communicate Master and Slave
The issue we are seeing is, the first slave handles all JMS messages instead of even distribution between slaves.
See configuration as below
Master
<bean id="PreProcess" class="com.job.tasklet.PreProcessTasklet" scope="step">
<constructor-arg index="0" value="${run.slave}"/>
<property name="maxNumberOfSlaves" value="#{jobParameters['max-slave-count']}"/>
</bean>
<bean id="PostProcess" class="com.job.tasklet.PostProcessTasklet" scope="prototype">
<constructor-arg index="0" ref="chpsJobDataSource"/>
</bean>
<bean id="partitioner" class="com.job.partition.DatabasePartitioner" scope="step">
<constructor-arg index="3" value="${max.row.count}"/>
</bean>
<bean id="partitionHandler" class="com.job.handler.StepExecutionAggregatorHandler">
<property name="stepName" value="processAutoHoldSlaveStep"/>
<property name="gridSize" value="${grid.size}"/>
<property name="replyChannel" ref="aggregatedGroupRuleReplyChannel"/>
<property name="messagingOperations">
<bean class="org.springframework.integration.core.MessagingTemplate">
<property name="defaultChannel" ref="groupRuleRequestsChannel"/>
</bean>
</property>
</bean>
<!-- Request Start -->
<int:channel id="groupRuleRequestsChannel" />
<int-jms:outbound-channel-adapter channel="groupRuleRequestsChannel" jms-template="jmsTemplateToSlave"/>
<bean id="jmsTemplateToSlave" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="receiveTimeout" value="5000"/>
<property name="defaultDestinationName" value="defaultRequest"/>
</bean>
<bean id="jmsTemplateFromSlave" class="org.springframework.jms.core.JmsTemplate" parent="jmsTemplateToSlave">
<property name="defaultDestinationName" value="defaultRequest"/>
</bean>
<!-- Response Test Start -->
<int:channel id="groupRuleReplyChannel">
<!-- <int:queue/> -->
</int:channel>
<int-jms:inbound-channel-adapter channel="groupRuleReplyChannel" jms-template="jmsTemplateFromSlave">
<int:poller id="defaultPoller" default="true" max-messages-per-poll="1" fixed-rate="3000" />
</int-jms:inbound-channel-adapter>
<!-- define aggregatedReplyChannel -->
<int:channel id="aggregatedGroupRuleReplyChannel">
<int:queue/>
</int:channel>
<int:aggregator ref="partitionHandler"
input-channel="groupRuleReplyChannel"
output-channel="aggregatedGroupRuleReplyChannel"
send-timeout="3600000"/>
Slave
<int:channel id="requestsChannel" />
<bean id="connectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">
<property name="brokerURL" value="${spring.activemq.broker-url}" />
<property name="trustAllPackages" value="true" />
</bean>
<int-jms:message-driven-channel-adapter id="jmsIn" destination-name="#{args[0]}" channel="requestsChannel" connection-factory="connectionFactory" max-messages-per-task="1"/>
<int:service-activator input-channel="requestsChannel" output-channel="replyChannel" ref="stepExecutionRequestHandler" />
<int:channel id="replyChannel" />
<int-jms:outbound-channel-adapter connection-factory="connectionFactory" destination-name="#{args[1]}" channel="replyChannel" />
Please advice if you have experience the issue.
Let me know if you need more information.
Note: I already search a lot at here and google but no luck for solution yet.
ActiveMQ uses a prefetch of 1000 by default see here.
In other words, the first (up to) 1000 partitions will go to the first consumer etc.
You can reduce the prefetch; 1 is probably fine for this application.
A simple message-based RPC is very easy to create. The server side exports the service, the client side uses a proxy.
What is the best way, to make the same thing with multiple repliers?
I want to send a request from a client. Then the client waits while all (maybe with timeout) replies are received.
You could use an aggregator with appropriate correlation and release strategies (and a group timeout).
EDIT:
Here's a version using a JMS Topic...
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost"/>
</bean>
</property>
<property name="sessionCacheSize" value="10"/>
</bean>
<bean id="requestTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="topic.demo"/>
</bean>
<bean id="replyQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="queue.reply"/>
</bean>
<int-stream:stdin-channel-adapter id="stdin" channel="stdinToJmsoutChannel"/>
<int:channel id="stdinToJmsoutChannel"/>
<int:chain input-channel="stdinToJmsoutChannel">
<int:header-enricher>
<int:header name="jms_replyTo" ref="replyQueue" />
</int:header-enricher>
<int-jms:outbound-channel-adapter destination="requestTopic" />
</int:chain>
<int-jms:message-driven-channel-adapter channel="jmsReplyChannel"
destination="replyQueue"/>
<int:channel id="jmsReplyChannel" />
<int:chain input-channel="jmsReplyChannel">
<int:aggregator group-timeout="5000" expire-groups-upon-timeout="false"
send-partial-result-on-expiry="true"
discard-channel="logLateArrivers"
correlation-strategy-expression="headers['jms_correlationId']"
release-strategy-expression="size() == 2"/>
<int-stream:stdout-channel-adapter append-newline="true"/>
</int:chain>
<int:logging-channel-adapter id="logLateArrivers" />
<!-- Subscribers -->
<int-jms:inbound-gateway request-channel="upcase" request-destination="requestTopic" />
<int-jms:inbound-gateway request-channel="upcase" request-destination="requestTopic" />
<int:transformer input-channel="upcase" expression="payload.toUpperCase()" />
Type requests into the console:
Please type something and hit <enter>
foo
[FOO, FOO]
bar
[BAR, BAR]
baz
[BAZ, BAZ]
Using Spring Integration for transferring message from one queue to other in Websphere MQ.
OutPut Channel shows message is going but I am not able to see in Queue from MQ Explorer.How the session commits ? and I am not able to stop the java application. How to gracefully stop with connection stop ?
where I am doing wrong ?
Here is the context config -
<int:logging-channel-adapter log-full-message="true" id="logger" level="INFO"/>
<bean id="jmsConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="hostName" value="localhost" />
<property name="port" value="1414" />
<property name="queueManager" value="TEST" />
<property name="transportType" value="1" />
</bean>
<bean id="inQueue" class="com.ibm.mq.jms.MQQueue">
<constructor-arg value="TESTQ" />
</bean>
<bean id="outQueue" class="com.ibm.mq.jms.MQQueue">
<constructor-arg value="DEST_QUEUE" />
</bean>
<int:channel id="readFromChannel">
<int:interceptors>
<int:wire-tap channel="logger"/>
</int:interceptors>
</int:channel>
<int:channel id="sendToChannel" >
<int:queue/>
<int:interceptors>
<int:wire-tap channel="logger"/>
</int:interceptors>
</int:channel>
<int-jms:message-driven-channel-adapter id="jmsInAdapter"
connection-factory="cachingConnectionFactory"
destination="inQueue"
channel="readFromChannel" />
<int-jms:message-driven-channel-adapter id="jmsOutAdapter"
connection-factory="cachingConnectionFactory"
destination="outQueue"
channel="sendToChannel" />
<bean id="myMessenger" class="test.MyMessenger" />
<int:service-activator id="servAct" input-channel="readFromChannel" output-channel="sendToChannel" ref="myMessenger" method="transfer"/>
If I understand your use-case correctly, you want to shift messages from TESTQ to DEST_QUEUE. But you have <int-jms:message-driven-channel-adapter> for both to read messages from them, but no one to put messages to DEST_QUEUE.
Your <int:service-activator> get message from readFromChannel and it means 'get message from TESTQ', but it places message to the sendToChannel. But it doesn't say that you place a message to the DEST_QUEUE.
That is because <int-jms:message-driven-channel-adapter> is for reading messages from JMS (MQ in your case).
To send message to JMS (to the DEST_QUEUE in your case) you have to use <int-jms:outbound-channel-adapter> and there is no reason to mark sendToChannel as <queue>