Unable to cache SFTP connection with Spring Integration - java

I need to transfer several small files via SFTP using spring integration, so I'd like to reuse a connection once established to avoid the overhead of creating a new one for every single message.
This is my current configuration:
<bean id="sftpTARGETSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<constructor-arg name="isSharedSession" value="true"/>
<property name="host" value="${TARGET.push.host}"/>
<property name="user" value="${TARGET.push.user}"/>
<property name="privateKey" value="classpath:${TARGET.push.keyFile}"/>
<property name="privateKeyPassphrase" value="${TARGET.push.keyFilePass}"/>
</bean>
<bean id="cachingSessionFactory"
class="org.springframework.integration.file.remote.session.CachingSessionFactory">
<constructor-arg ref="sftpTARGETSessionFactory"/>
<property name="poolSize" value="2"/>
<property name="sessionWaitTimeout" value="2000"/>
</bean>
<int-sftp:outbound-channel-adapter
id="sftpTARGET"
session-factory="cachingSessionFactory"
channel="ftpTARGET.channel"
charset="UTF-8"
remote-file-separator="/"
remote-directory="${TARGET.push.path}"
mode="REPLACE"/>
Unfortunately this doesn't work as I expected: every message opens a new ssh connection.
any hint on what's going wrong?
Using spring-integration 4.1.6 here.
thanks!

Related

Closing conection from pool in runtime oracle-data-source

I have legacy web application. Witch uses jdbcTemplate to execute stored procedures from DB (Oracle), procedures located at packages. Problem is, when database developers compiles that packages im getting Expceptions sometihng like existing state of packages been changed (ora 4061). and they does that 1 or 2 times per week. Then i have to restart application to restart pool. app uses OracleDataSource. i can't change anything at that db but can change pool manager. so the question is. is it possible to close that connection? not just return to pool. and get new connection(from pool) if that Exception apears? thanks !!
people sugested to re-execute that stored procedure when that error apears. It doest worked.
<bean id="ds_name" class="oracle.jdbc.pool.OracleDataSource"
destroy-method="close">
<property name="connectionCachingEnabled" value="true" />
<property name="URL" value="****" />
<property name="user" value="user" />
<property name="password" value="pass" />
<property name="connectionCacheProperties">
<value>
MinLimit:1
MaxLimit:100
InitialLimit:1
ConnectionWaitTimeout:120
InactivityTimeout:180
ValidateConnection:true
</value>
</property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="ds_name" />
</bean>

Hazelcast-client configuration on AWS

My question regards hazelcast-client configuration.
From what I understand, when configured properly the client is supposed to fetch hazelcast server nodes IPs automatically from the AWS api , the problem is doesn't even try connect.
Here's some log I found.
Caused by: java.lang.IllegalStateException: Unable to connect to any address in the config! The following addresses were tried: []
at com.hazelcast.client.spi.impl.ClusterListenerSupport.connectToCluster(ClusterListenerSupport.java:178)
at com.hazelcast.client.spi.impl.ClientClusterServiceImpl.start(ClientClusterServiceImpl.java:189)
also here's client conifig
<bean id="hazelcastInstance" class="com.hazelcast.client.HazelcastClient" factory-method="newHazelcastClient">
<constructor-arg>
<bean class="com.hazelcast.client.config.ClientConfig">
<property name="groupConfig">
<bean class="com.hazelcast.config.GroupConfig">
<property name="name" value="dev"/>
</bean>
</property>
<property name="properties">
<props>
<prop key="hazelcast.icmp.enabled">true</prop>
</props>
</property>
<property name="networkConfig">
<bean class="com.hazelcast.client.config.ClientNetworkConfig">
<property name="awsConfig">
<bean class="com.hazelcast.client.config.ClientAwsConfig">
<property name="insideAws" value="true" />
<property name="enabled" value="${hazelcast.aws.enabled:false}" />
<property name="region" value="${hazelcast.aws.region:set-me}" />
<property name="accessKey"value="key" />
<property name="secretKey" value="secret"/>
<property name="hostHeader" value="ec2.amazonaws.com"/>
<property name="iamRole" value="${hazelcast.aws.iam.role:#{null}}"/>
<!-- <property name="securityGroupName" value="${hazelcast.aws.securityGroupName:#{null}}" /> -->
<property name="tagKey" value="${hazelcast.aws.tagKey:hazelcast-cluster}" />
<property name="tagValue" value="${hazelcast.aws.tagValue:#{null}}" />
<property name="connectionTimeoutSeconds" value="${hazelcast.aws.connectionTimeout:15}" />
</bean>
</property>
</bean>
</property>
</bean>
</constructor-arg>
</bean>
also tried to force server ip, that works. I need the client to discover server ips automatically. any clue ?
You need to use the discovery plugin mechanism if you want the client to discover clusters on AWS (or any other cloud). The old AWS discovery was for members only.
Please see https://github.com/hazelcast/hazelcast-aws

ActiveMQ: How to prevent message from going to "Dispatched Queue"

I'm using ActiveMQ with the spring framework.
I have two consumers setup in the jms container. When I send 4 message to the queue, and some of the message are transferred to the "Dispatched Queue", because it takes a long time to the consumer to process the message.
I'm trying to find the way to prevent the message from going to the "Dispatched Queue", that is, I want them to be available to any consumer that is ready to consume the message.
I tried to set pre-fetch to 0, but it doesn't seem to work at all.
<bean id="prefetchPolicy" class="org.apache.activemq.ActiveMQPrefetchPolicy">
<property name="queuePrefetch" value="0"/>
</bean>
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<constructor-arg index="0" value="tcp://localhost:61616" />
<property name="prefetchPolicy" ref="prefetchPolicy"/>
</bean>
The following is the setup for my jms container:
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="defaultDestination" />
<property name="messageListener" ref="messageListener" />
<property name="concurrentConsumers" value="2" />
</bean>
I found the problem. I had the same beans declared twice at two different places. The second bean that was loaded did not have pre-fetch set to 0 and therefore it didn't work out.
The above setup I posted works!
Thank you!

How to get TimeToLive working on JmsTemplate?

I am trying to set the TTL on JmsTemplate but the messages never expire. When I set a TTL on a message using the ActiveMQ Web Console it does expire after the set period.
This is what I have now:
<bean id="shortTtlJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<constructor-arg ref="jmsConnectionFactory"/>
<property name="explicitQosEnabled" value="true"/>
<property name="deliveryPersistent" value="false"/>
<property name="receiveTimeout" value="10000"/>
<property name="timeToLive" value="10000"/>
</bean>
<bean id="shortTtlJmsMessagingTemplate" class="org.springframework.jms.core.JmsMessagingTemplate">
<constructor-arg ref="shortTtlJmsTemplate"/>
</bean>
The documentation only says that I have to set explicitQosEnabled to true but apparently this is not enough. Does anyone know what I am doing wrong?
Apparently it wasn't working due to a clock synchronisation issue. The clocks are in sync now and everything is working as expected.

Producer and Consumer in Spring Jms use same connection factory?

I have a component which reads messages from a queue and meanwhile sends the processed messages to another queue. Therefore, this component is both a message consumer and producer. For configuring them, I need a connection factory for consuming and another connection factory for the producing. Here is part of the spring configuration.
<!-- Configuration for listener -->
<bean id="mdc.TargetConnectionFactory4Listener" class="com.tibco.tibjms.TibjmsConnectionFactory">
<property name="serverUrl" value="tcp://localhost:7222"/>
</bean>
<bean id="mdc.ConnectionFactory4Listener" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="mdc.TargetConnectionFactory"/>
<property name="username" value="admin" />
<property name="password" value="test" />
</bean>
<bean id="mdc.InputQueue" class="com.tibco.tibjms.TibjmsQueue">
<constructor-arg>
<value>INPUT_QUEUE</value>
</constructor-arg>
</bean>
<bean id="mdc.JmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="mdc.ConnectionFactory4Listener" />
<property name="destination" ref="mdc.InputQueue" />
<property name="messageListener" ref="mdc.MessageReceiver" />
......
</bean>
<!-- Configuration for sender -->
<bean id="mdc.TargetConnectionFactory4Sender" class="com.tibco.tibjms.TibjmsQueue">
<property name="serverUrl" value="tcp://localhost:7222"/>
</bean>
<bean id="mdc.CachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="mdc.TargetConnectionFactory4Sender" />
<property name="sessionCacheSize" value="50" />
</bean>
<bean id="mdc.OutputQueue" class="com.tibco.tibjms.TibjmsQueue">
<constructor-arg>
<value>DISCOVERY_QUEUE</value>
</constructor-arg>
</bean>
<bean id="mdc.JmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="mdc.CachingConnectionFactory" />
</bean>
<bean id="mdc.MessageReceiver" class="net.siemens.discovery.queue.QueueMessageListener">
<property name="jmsTemplate" ref="mdc.JmsTemplate" />
<property name="destination" ref="mdc.OutputQueue" />
......
</bean>
The two queues are running on the same EMS server. Some has opinions about this configurations: they can be configured by using only one ConnectionFactory and two instances are not necessary. However, if I use one ConnectionFactory instance, then the instance is used both in the DefaultMessageListenerContainer and the CachingConnectionFactory (further used in JmsTemplate). I don't know whether they have impact on each other.
It is perfectly normal to use a single connection factory; it is very unusual to use 2 factories in this case.
In fact, if you want to perform JmsTemplate operations on the container thread and you want the interactions to run in a transaction (sessionTransacted = true in the container), then you must use the same connection factory. This allows everything to roll back if there's an exception.
When using a caching connection factory in the listener container you should set the connection factory cacheConsumers to false. (See this answer for more information.

Categories

Resources