Spring Integration exception always not reaching errorChannel - spring

<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")

Related

pass message to producer through jms

How to pass a message to producer(a method defined to sent message to activemq) through spring integration.
Actual requirement is, i need insert data to database and that data to be moved to a queue in activemq,both the operations need to be happened parallely. How can i do it.
<jms:message-driven-channel-adapter id="helloWorldJMSAdapater" destination="helloWorldJMSQueue" connection-factory="jmsConnectionFactory"
channel="postChannel" />
<int:channel id="requestChannel" />
<int:channel id="outputChannel" />
<int-http:inbound-gateway request-channel="requestChannel"
reply-channel="outputChannel" supported-methods="GET" path="/register"
view-name="register">
<int-http:request-mapping />
</int-http:inbound-gateway>
<int-http:inbound-gateway request-channel="postChannel"
reply-channel="outputChannel" supported-methods="POST" path="/registerNew"
error-channel="errorChannel" view-name="login">
</int-http:inbound-gateway>
<int-jdbc:outbound-channel-adapter
query="insert into user_registration (USER_FSTNAME,USER_ADDRESS,USER_STATE,USER_CITY,USER_OCCUPATION,USER_EMAIL,USER_CONTACT,USER_PASSWORD)
values (:fstName,:addrss,:state,:city,:occupation,:email,:contact,:password)"
channel="postChannel" data-source="dataSource" id="sample" sql-parameter-source-factory="spelSource" />
<int:service-activator ref="userService" input-channel="requestChannel"
output-channel="outputChannel" method="message"/>
<bean id="spelSource"
class="org.springframework.integration.jdbc.ExpressionEvaluatingSqlParameterSourceFactory">
<property name="parameterExpressions">
<map>
<entry key="fstName" value="payload[firstName]" />
<entry key="lstName" value="payload[lastName]" />
<entry key="addrss" value="payload[address]" />
<entry key="state" value="payload[state]" />
<entry key="city" value="payload[city]" />
<entry key="occupation" value="payload[occupation]" />
<entry key="email" value="payload[email]"/>
<entry key="contact" value="payload[contact]"/>
<entry key="password" value="payload[password]"/>
</map>
</property>
</bean>
Use a <publish-subscribe-channel/> and subscribe both endpoints to it. They will be executed serially by default, or in parallel if you add a task-executor to the channel.

Transfer how to deliver message to Gateway?

https://github.com/spring-projects/spring-integration-samples/tree/master/intermediate/tcp-client-server-multiplex
I saw this exmaple. So, I was changed architecture.
send model
receive model
And I have a question.
I don't understand transfer's role in send model.
I understand Aggregator delivery message to Transfer.
But, I don't understand How to deliver message to gateway.
How to deliver?
That is my spring integration config.
It is Send app setting,
<!-- telegram bean -->
<bean id="byteArrayRawSerializer" class="org.springframework.integration.ip.tcp.serializer.ByteArrayRawSerializer">
<property name="maxMessageSize" value="2000"/>
</bean>
<bean id="myCorrelationStrategy" class="com.test.util.MyCorrelationStrategy"/>
<!-- online connection factory -->
<int-ip:tcp-connection-factory id="server" type="server" port="20001" single-use="false" lookup-host="false" so-timeout="60000" serializer="byteArrayRawSerializer" deserializer="byteArrayRawSerializer" />
<int-ip:tcp-connection-factory id="client" type="client" host="localhost" port="10001" single-use="false" so-timeout="60000" serializer="byteArrayRawSerializer" deserializer="byteArrayRawSerializer" />
<!-- Send -->
<int:gateway id="sendGateway"
service-interface="com.test.MySendGateway"
default-reply-timeout="20000"
default-request-channel="sendChannel"/>
<int:publish-subscribe-channel id="sendChannel" />
<int-ip:tcp-outbound-channel-adapter id="sendAdapter" order="2" channel="sendChannel" connection-factory="client" />
<int:bridge input-channel="batchSendChannel" output-channel="toSendAggregator" order="1"/>
<int:channel id="toSendAggregator" datatype="byte[]"/>
<int:aggregator input-channel="toSendAggregator"
output-channel="toSendTransformer"
expire-groups-upon-completion="true"
correlation-strategy="myCorrelationStrategy"
correlation-strategy-method="getCorrelationKey"
release-strategy-expression="size() == 2" />
<int:transformer input-channel="toSendTransformer" expression="payload.get(1)"/>
<int-ip:tcp-inbound-channel-adapter id="sendReplyAdapter" channel="toSendAggregator" connection-factory="client" />
<!-- Receive -->
<int-ip:tcp-inbound-channel-adapter id="inboundAdapter" channel="batchInboundChannel" connection-factory="batchReceiveServer" />
<int-ip:tcp-outbound-channel-adapter id="outboundAdapter" channel="batchOutboundChannel" connection-factory="batchReceiveServer"/>
<int:channel id="batchInboundChannel" />
<int:channel id="batchOutboundChannel"/>
<int:service-activator id="myReceiveServiceActivator" method="receive" input-channel="batchInboundChannel">
<bean class="com.test.endpoint.MyReceiveServiceActivator" />
</int:service-activator>
And, It is Delivery app setting(center of picture),
<!-- Bean load -->
<bean id="byteArrayRawSerializer" class="org.springframework.integration.ip.tcp.serializer.ByteArrayRawSerializer">
<property name="maxMessageSize" value="2000"/>
</bean>
<!-- Connection factory -->
<int-ip:tcp-connection-factory id="server" type="server" port="30001" using-nio="true" single-use="false" lookup-host="false" so-timeout="10000" serializer="byteArrayRawSerializer" deserializer="byteArrayRawSerializer" />
<int-ip:tcp-connection-factory id="client" type="client" host="${RemoteTarget.ip}" port="${RemoteTarget.port}" using-nio="true" single-use="false" so-timeout="10000" serializer="byteArrayRawSerializer" deserializer="byteArrayRawSerializer" />
<!-- Connection factory -->
<int-ip:tcp-connection-factory id="inboundServer" type="server" port="10001" using-nio="true" single-use="false" lookup-host="false" so-timeout="${server.outbound.connectionTimeout}" serializer="byteArrayRawSerializer" deserializer="byteArrayRawSerializer" />
<int-ip:tcp-connection-factory id="inboardClient" type="client" host="localhost" port="20001" using-nio="true" single-use="false" so-timeout="10000" serializer="byteArrayRawSerializer" deserializer="byteArrayRawSerializer" />
<int-ip:tcp-inbound-channel-adapter id="receiveAdapter" channel="receiveChannel" connection-factory="server" auto-startup="true"/>
<int-ip:tcp-inbound-channel-adapter id="sendReplyAdapter" channel="sendReplyChannel" connection-factory="client" auto-startup="true"/>
<int:channel id="receiveChannel"/>
<int:channel id="sendReplyChannel"/>
<int-ip:tcp-outbound-channel-adapter id="receiveAdapter.inboard" channel="receiveChannel" connection-factory="inboundServer" />
<int-ip:tcp-outbound-channel-adapter id="sendReplyAdapter.inboard" channel="sendReplyChannel" connection-factory="inboardClient" />
<int-ip:tcp-outbound-channel-adapter id="sendAdapter" channel="sendChannel" connection-factory="client" />
<int-ip:tcp-outbound-channel-adapter id="receiveReplyAdapter" channel="receiveReplyChannel" connection-factory="server" />
<int:channel id="sendChannel" />
<int:channel id="receiveReplyChannel"/>
<int:router id="outRouter" input-channel="toRouter" method="route" auto-startup="true">
<bean class="com.test.endpoint.MyRouter"/>
</int:router>
<int:channel id="toRouter"/>
<int-ip:tcp-inbound-channel-adapter id="sendAdapter.inboard" channel="toRouter" connection-factory="inboundServer" auto-startup="true"/>
<int-ip:tcp-inbound-channel-adapter id="receiveReplyAdapter.inboard" channel="toRouter" connection-factory="inboardClient" auto-startup="true"/>
But, When I call gw.send(msg), it is not work,
(exactly, message stop at the delivery machine's 'sendAdapter.inboard' until timeout and router get this message....
I an not sure what is transfer in your ar3chitecture either.
According the sample you show, we have:
gateway -> outbound-channel-adapter
|-> aggregator
inbound-channel-adapter->aggregator->transformer
Where gateway sends its request to both TCP Outbound Channel Adapter and Aggregator, just because of <publish-subscribe-channel id="input" />.
As we know gateway is a request/reply component. When it sends requests, it waits for reply, because of the contract:
public interface SimpleGateway {
String send(String text);
}
In this case the Gateway add TemporaryReplyChannel as a replyChannel header to wait for reply.
The reply is produced when we don't specify the output-channel on the last downstream flow consumer.
In our case it is exactly the <transformer> after <aggregator>:
<transformer input-channel="toTransformer.client"
expression="payload.get(1)"/> <!-- The response is always second -->
I think that is a trick what you are looking for. It is called replyChannel header in the Consumer logic.

Spring Integration Aggregator + JDBC Message Store performance

The performance of aggregator to process JMS messages along with persistence message store is very low. Like for a simple example given below the messages processed are between 25-28 msgs per second.
Is this the normal behavior? Or am I doing something wrong here ?
<!-- ###################### Inbound Message Adapter ####################### -->
<int-jms:message-driven-channel-adapter
id="xmlInboundMessageAdapter"
channel="msgUnmarshallingChannel"
connection-factory="jmsConnectionFactory"
destination="messsageQueue"
acknowledge="transacted"
concurrent-consumers="1"
max-concurrent-consumers="5"
auto-startup="true"/>
<!-- ###################### MSG UN-MARSHALLER ####################### -->
<int:channel id="msgUnmarshallingChannel" />
<int:chain input-channel="msgUnmarshallingChannel" output-channel="msgHeaderEnricherChannel">
<int-xml:unmarshalling-transformer unmarshaller="msgUnmarshaller" />
</int:chain>
<bean id="msgUnmarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="com.msg.something" />
<property name="supportJaxbElementClass" value="true" />
</bean>
<int:channel id="msgHeaderEnricherChannel" />
<!-- ###################### SOME HEADER ENRICHMENT ####################### -->
<int:chain input-channel="msgHeaderEnricherChannel" output-channel="msgAggreggatorChannel">
<int:header-enricher>
<int:header name="CORRELATION_ID" expression="payload.notificationTypeId" />
</int:header-enricher>
</int:chain>
<int:channel id="msgAggreggatorChannel" />
<int:channel id="msgAggreggatorDiscardChannel" />
<!-- ###################### AGGREGATOR WITH PERSISTENCE MSG STORE ####################### -->
<int:aggregator
auto-startup="true"
send-timeout="-1"
message-store="messageStore"
input-channel="msgAggreggatorChannel"
output-channel="nullChannel"
discard-channel="msgAggreggatorDiscardChannel"
correlation-strategy="msgCorrelationStrategy"
release-strategy="msgReleaseStrategy"
expire-groups-upon-completion="true" />
<!-- ###################### MSG STORE ####################### -->
<bean id="messageStore" class="org.springframework.integration.jdbc.JdbcMessageStore">
<property name="dataSource" ref="dataSourceSPJDBC" />
<property name="lobHandler" ref="oracleLobHandler" />
</bean>
<bean id="oracleLobHandler" class="org.springframework.jdbc.support.lob.OracleLobHandler" />
<bean id="msgCorrelationStrategy" class="org.springframework.integration.aggregator.HeaderAttributeCorrelationStrategy">
<constructor-arg value="CORRELATION_ID" />
</bean>
<bean id="msgReleaseStrategy" class="org.springframework.integration.aggregator.MessageCountReleaseStrategy">
<constructor-arg value="10"/>
</bean>
It's a known problem for very large groups.
Which version of Spring Integration are you using? There have been a number of improvements made in this area, the latest being in 4.2.
The current version is 4.2.4; let us know if you're still seeing problems with that version.

how to polling int:gateway to start int-ftp:outbound-gateway?

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=".*"/>

Spring Integration queue is not getting message but channel is getting

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>

Resources