After my poller fetches data from DB, I am calling an external service.
After getting response from that service, I want to do call another systems in a separate thread. Means, after getting response, my poller should take another record and send.In addition calling other systems should work in parallel.
For this I used a direct channel for receiving the data from DB. Used a service activator for sending request to external service. The response is passed to an executer channel.can anyone please tell me whether the below configuration is correct for the scenario ?
For clarity I am sharing the poller.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:task="http://www.springframework.org/schema/task" xmlns:int-http="http://www.springframework.org/schema/integration/http"
xmlns:stream="http://www.springframework.org/schema/integration/stream"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-4.1.xsd
http://www.springframework.org/schema/integration/stream
http://www.springframework.org/schema/integration/stream/spring-integration-stream-4.1.xsd
http://www.springframework.org/schema/integration/http
http://www.springframework.org/schema/integration/http/spring-integration-http-4.1.xsd
http://www.springframework.org/schema/integration/jdbc
http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc-4.1.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd">
<!-- <import resource="persistence-config.xml" /> <int:channel id="inchannel">
</int:channel> <int:channel id="outchannel"> <int:dispatcher task-executor="taskExecutor"/>
</int:channel> <task:executor id="taskExecutor" pool-size="2"/> <bean id="poller"
class="main.java.com.as.poller.PollerService" /> <int:service-activator input-channel="inchannel"
output-channel="outchannel" ref="poller" method="sendMessage" /> -->
<int-jdbc:inbound-channel-adapter id="dataChannel"
query="select loyalty_id, process_id,mobile_uid from TBL_RECEIPT where r_cre_time=(select min(r_cre_time) from TBL_RECEIPT where receipt_status=0)"
data-source="dataSource" max-rows-per-poll="1"
update="update TBL_RECEIPT set receipt_status=11 where loyalty_id in (:loyalty_id)">
<int:poller fixed-rate="5000">
</int:poller>
</int-jdbc:inbound-channel-adapter>
<bean id="poller" class="main.java.com.as.poller.PollerService" />
<int:channel id="executerchannel">
<int:dispatcher task-executor="taskExecutor"/>
</int:channel>
<task:executor id="taskExecutor" pool-size="20"/>
<int:service-activator input-channel="dataChannel"
output-channel="executerchannel" ref="poller" method="processMessage" />
<int:service-activator input-channel="executerchannel" ref="poller" method="processTpg">
</int:service-activator>
<stream:stdout-channel-adapter id="executerchannel"/>
No; it's not correct (it is almost correct).
<stream:stdout-channel-adapter id="executerchannel"/>
this overrides your executor channel definition (an outbound adapter with no channel attribute creates a channel with that id).
You will end up with a simple direct channel with 2 subscribers (stdout and your service activator) - they will get alternate messages.
I am not sure why you added that element; remove it or subscribe it to some other channel.
If you want it to go to both places; change the channel to a <publish-subscribe-channel/> with an executor.
Related
I am doing Spring Integration with Server and Client request/response demo. The request comes with a Byte array which is to be converted to Object. Then the request comes to the input channel, I need to check which class is to be send to the service activator. Then the service activator will send it to the reply channel.
<bean id="javaSerializer"
class="org.springframework.core.serializer.DefaultSerializer"/>
<bean id="javaDeserializer"
class="org.springframework.core.serializer.DefaultDeserializer"/>
<!-- single-use="true" : A new message has to wait until the reply to the previous message has been received -->
<int-ip:tcp-connection-factory id="server"
type="server"
host="localhost"
port="10101"
single-use="true"
so-timeout="10000"
serializer="javaSerializer"
deserializer="javaDeserializer"
task-executor="severTaskExecutor"/>
<int-ip:tcp-inbound-gateway id="inGateway"
request-channel="inputChannel"
reply-channel="replyChannel"
connection-factory="server"
reply-timeout="10000"/>
<int:channel id="inputChannel"/>
<!-- How to switch the request to the different channel??? -->
<int:channel id="myChannelOne"/>
<int:channel id="myChannelTwo"/>
<int:service-activator
input-channel="myChannelOne"
output-channel="replyChannel"
ref="myServiceOne"
method="get" />
<int:service-activator
input-channel="myChannelTwo"
output-channel="replyChannel"
ref="myServiceTwo"
method="get" />
<int:channel id="replyChannel"/>
<bean id="myServiceOne" class="com.my.demo.MyServiceOne"/>
<bean id="myServiceTwo" class="com.my.demo.MyServiceTwo"/>
Use a payload type router https://docs.spring.io/spring-integration/docs/current/reference/html/message-routing.html#router-implementations-payloadtyperouter
<int:payload-type-router input-channel="routingChannel">
<int:mapping type="java.lang.String" channel="stringChannel" />
<int:mapping type="java.lang.Integer" channel="integerChannel" />
</int:payload-type-router>
I am working on a high-volume integration with using spring integration tcp and I only send a request and receive more than millions of data over one connection and the time between two receiving message is lower than 100 milliseconds.
Here is my context xml and I am using TCPOutboundGateway.
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration https://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/ip https://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">
<bean class="org.springframework.integration.samples.tcpclientserver.EchoService"
id="echoService"/>
<bean class="org.springframework.integration.samples.tcpclientserver.ByteArrayToStringConverter"
id="javaDeserializer"/>
<int-ip:tcp-connection-factory
apply-sequence="true" deserializer="javaDeserializer"
host="127.0.0.1"
id="TCPClientFactory1"
port="443"
single-use="false"
type="client"
/>
<int-ip:tcp-outbound-gateway
async="true" close-stream-after-send="false" connection-factory="TCPClientFactory1"
id="outGateway"
remote-timeout="10000"
reply-channel="serverBytes2StringChannel"
reply-timeout="10000"
request-channel="input"
request-timeout="10"
/>
<int:channel id="input"/>
<int:channel id="toSA"/>
<int:gateway default-request-channel="input"
id="gw"
service-interface="org.springframework.integration.samples.tcpclientserver.SimpleGateway"/>
<int:object-to-string-transformer auto-startup="true" id="serverBytes2String"
input-channel="serverBytes2StringChannel"
output-channel="toSA"/>
<int:service-activator
input-channel="toSA"
method="test"
ref="echoService"
/>
<int:transformer expression="payload.failedMessage.payload + ':' + payload.cause.message"
id="errorHandler"
input-channel="errorChannel"/>
</beans>
I took an example from github.
My issue is; I can successfully handle and process first received message. But the rest is got below exception.
20:21:34.550 [pool-1-thread-1] ERROR org.springframework.integration.ip.tcp.TcpOutboundGateway - Cannot correlate response - no pending reply for 127.0.0.1:443:57385:e164052f-64e5-4d41-9d46-4a12bad12cd4
I read the source code of TcpOutboundGateway and also read caching client connection factory document but could not found a proper way to achieve solution.
The gateway is not designed for that scenarion it only supports 1 reply per request.
You can use a pair of outbound/inbound channel adapters, instead of the gateway, for scenarios like this.
The upcoming 5.4 release has an enhancement to the gateway to support this scenario.
I'm trying to learn Spring Integration and for this i would like to create an application like this:
From Oracle i send messages (on Oracle Queue), this message will be intercepted from a Java application (build with Spring Integration) and the application will send an email based on message received. The message will contain To: - Cc: and the text to send.
To make this kind of communication i've decided to use JMS (i think in Oracle this is made with Oracle AQ).
In the database i've already created the Queue and now i'm trying to create a simple applicationContext.xml to start this handshake.
Looking on the net i've found really few articles about this (Spring Integration + Oracle AQ) and i'm getting some error. The main error is this: java.lang.ClassNotFoundException: oracle.jms.AQjmsFactory
Right now this is my applicationContext.xml
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:orcl="http://www.springframework.org/schema/data/orcl"
xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
http://www.springframework.org/schema/data/orcl http://www.springframework.org/schema/data/orcl/spring-data-orcl-1.0.xsd">
<int:channel id="inbound" />
<int:channel id="outbound" />
<bean id="simpleMessageListener" class="it.dirimo.SimpleMessageListener" />
<int-jms:inbound-channel-adapter
channel="inbound"
connection-factory="connectionFactory"
destination-name="Q1">
<int:poller fixed-delay="1000" />
</int-jms:inbound-channel-adapter>
<int:service-activator input-channel="inbound" output-channel="outbound" ref="simpleMessageListener" method="onMessage" />
<int-jms:outbound-channel-adapter id="jmsOut"
channel="outbound"
connection-factory="connectionFactory"
destination-name="sampleQueue" />
<int:poller id="poller" default="true" fixed-delay="10000" />
<orcl:aq-jms-connection-factory id="connectionFactory"
data-source="dataSource"
use-local-data-source-transaction="true"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" lazy-init="false">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#localhost:1521:ORCL" />
<property name="username" value="user" />
<property name="password" value="password" />
</bean>
</beans>
Maybe i'm using "old" technologies (for example i've seen for the first time this org.apache.commons.dbcp.BasicDataSource)
Unfortunally i'm so new about Spring Integration and i've seen for the first time Oracle Queue (i'm using Oracle for work but never used any kind of Queue).
Some advice of how to proceed will be apreciated :)
EDIT 1
To solve the problem about the AQjmsFactory need to include aqapi.jar
java.lang.ClassNotFoundException: oracle.jms.AQjmsFactory
This simply means you are missing the jar that contains that class from the classpath.
Oracle, typically, requires that you manually download their jars from them directly.
I am having issues with threads getting parked at my Service Activators that leads to files hanging in the SftpGatewayChannel when the pool is depleted. I think it is related to the SA's having a void return, which is correct because they are only incrementing metrics.
I was able to work around the issue by adding a default-reply-timeout to the SftpGateway, but this is not ideal since there is retry advice and I don't want the threads to timeout if there is a connection issue. I would like a solution that returns the threads to the pool after a successful upload and call to the "Success" Service Activator.
<task:executor id="Tasker" rejection-policy="CALLER_RUNS" pool-size="${MaxThreads}" />
<int:channel id="SftpGatewayChannel">
<int:dispatcher task-executor="Tasker" />
</int:channel>
<int:service-activator id="SegmentStart" input-channel="SftpGatewayChannel" ref="SftpGateway" />
<int:gateway id="SftpGateway" default-request-channel="SftpOutboundChannel" error-channel="ErrorChannel" />
<int:channel id="SftpOutboundChannel" datatype="java.lang.String,java.io.File,byte[]" />
<int-sftp:outbound-channel-adapter id="SftpOutboundAdapter"
session-factory="SftpCachingSessionFactory" channel="SftpOutboundChannel" charset="UTF-8" >
<int-sftp:request-handler-advice-chain>
<ref bean="exponentialRetryAdvice" />
<bean id="SuccessAdvice" class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice" >
<property name="successChannel" ref="SuccessChannel"/>
<property name="onSuccessExpression" value="true"/>
</bean>
</int-sftp:request-handler-advice-chain>
</int-sftp:outbound-channel-adapter>
<int:channel id="ErrorChannel">
<int:interceptors>
<int:wire-tap channel="FailureChannel" />
</int:interceptors>
</int:channel>
<int:channel id="AttemptChannel" />
<int:channel id="SuccessChannel" />
<int:channel id="FailureChannel" />
<int:service-activator id="AttemptMetrics" input-channel="AttemptChannel"
expression="T(MetricsCounter).addAttempt()" />
<int:service-activator id="SuccessMetrics" input-channel="SuccessChannel"
expression="T(MetricsCounter).addSuccesses(inputMessage.Headers.messages.size())" />
<int:service-activator id="FailureMetrics" input-channel="FailureChannel"
expression="T(MetricsCounter).addFailures(payload.getFailedMessage().Headers.messages.size())" />
Yes, gateways expect a reply by default. Instead of using the default RequestReplyExchanger you could use a service-interface method with a void return void process(Message<?> m).
Alternatively, as you have done, simply add default-reply-timeout="0" on your gateway and the thread will return immediately without waiting for a reply (that will never come).
... but this is not ideal ...
The reply timeout clock only starts when the thread returns to the gateway, so it will have no impact on the downstream flow.
I have a requirement to poll a mail server. As my project already in Spring i used Spring-Integration to poll the mail server. I was successful in that. But now i have to poll multiple emails. can some body let me know how to do it.
This is the sample code i used to poll a single mail.
<util:properties id="javaMailProperties">
<prop key="mail.imap.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
<prop key="mail.imap.socketFactory.fallback">false</prop>
<prop key="mail.store.protocol">imaps</prop>
<prop key="mail.debug">false</prop>
</util:properties>
<mail:inbound-channel-adapter id="imapAdapter"
store-uri="${imap.uri}"
channel="recieveEmailChannel"
should-delete-messages="false"
should-mark-messages-as-read="true"
auto-startup="true"
java-mail-properties="javaMailProperties">
<int:poller fixed-delay="${imap.poolerSecondsDelay}" time-unit="SECONDS"/>
</mail:inbound-channel-adapter>
<int:channel id="recieveEmailChannel">
<int:interceptors>
<int:wire-tap channel="logger"/>
</int:interceptors>
</int:channel>
<int:logging-channel-adapter id="logger" level="DEBUG"/>
<int:service-activator input-channel="recieveEmailChannel" ref="emailReceiverService" method="receive"/>
<bean id="emailReceiverService" class="com.usbank.hermes.serviceimpl.EmailReceiverService">
</bean>
Add the "max-messages-per-poll" to your poller.
ie:
<int:poller max-messages-per-poll="10" fixed-delay="${imap.poolerSecondsDelay}" time-unit="SECONDS"/>
which should fetch 10 mails from the queue each poll.