How is "acknowledge" used? - spring-integration

I am trying to integrate my application with JMS Queues (using ActiveMQ).
My requirement is, that once the message has been read from the input queue, message should not be removed from the queue. Rather I want to send an acknowledgement that application has received that message.
I am not able to understand the exact usage of property "acknowledge".
My code is as below:
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd
http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Component scan to find all Spring components -->
<context:component-scan base-package="com.poc.springinteg._7" />
<!-- -->
<bean id="remoteJndiTemplate" class="org.springframework.jndi.JndiTemplate" lazy-init="false">
<property name="environment">
<props>
<prop key="java.naming.provider.url">tcp://localhost:61616</prop>
<prop key="java.naming.factory.url.pkgs">org.apache.activemq.jndi</prop>
<prop key="java.naming.factory.initial">org.apache.activemq.jndi.ActiveMQInitialContextFactory</prop>
<prop key="connectionFactoryNames">DefaultActiveMQConnectionFactory,QueueConnectionFactory</prop>
<prop key="queue.SendReceiveQueue">org.apache.geronimo.configs/activemq-ra/JCAAdminObject/SendReceiveQueue</prop>
<prop key="queue.SendQueue">org.apache.geronimo.configs/activemq-ra/JCAAdminObject/MDBTransferBeanOutQueue</prop>
</props>
</property>
</bean>
<bean id="remoteConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="false">
<property name="jndiTemplate" ref="remoteJndiTemplate"/>
<property name="jndiName" value="QueueConnectionFactory"/>
<property name="lookupOnStartup" value="true" />
<property name="proxyInterface" value="javax.jms.ConnectionFactory" />
</bean>
<!-- writing queue -->
<bean id="destinationqueue"
class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0">
<value>OutputQueue_7</value>
</constructor-arg>
</bean>
<int:channel id="outbound"/>
<int-jms:outbound-channel-adapter id="jmsOut"
channel="outbound"
connection-factory="remoteConnectionFactory"
destination="destinationqueue" />
<!-- reading queue -->
<bean id="sourceQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0">
<value>OutputQueue_7</value>
</constructor-arg>
</bean>
<bean id="messageListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="remoteConnectionFactory"/>
<property name="destination" ref="sourceQueue"/>
<property name="maxConcurrentConsumers" value="10"/>
<property name="concurrentConsumers" value="1"/>
<property name="autoStartup" value="true"/>
</bean>
<int:channel id="inbound"/>
<int-jms:message-driven-channel-adapter id="jmsIn"
channel="inbound"
extract-payload="false"
container="messageListenerContainer" />
<int:service-activator input-channel="inbound"
output-channel="outbound"
ref="messageReader"
method="onMessage" />
</beans>
-- Message Reader Class
import javax.jms.JMSException;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
#Component("messageReader")
public class MessageReader
{
#ServiceActivator
public void onMessage(Message inboundMessage) {
System.out.println(" -------Message Read Start--------");
System.out.println(inboundMessage.getHeaders());
System.out.println(" -------Message Headers Reading completed--------");
System.out.println("payload-->" + inboundMessage.getPayload().getClass());
String payload = inboundMessage.getPayload().toString();
System.out.println("payload value-->" + payload);
org.apache.activemq.command.ActiveMQTextMessage obj = (org.apache.activemq.command.ActiveMQTextMessage)inboundMessage.getPayload();
System.out.println("Object-->" + obj);
String var = null;
try {
var = obj.getText();
System.out.println("Datastructure-->" + obj.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
---- Message Writer Class
#Component("sendMessage")
public class SendMessage {
#Autowired
private MessageChannel outbound;
public void send(String name)
{
Entity entity = new Entity(1,"anuj");
Message<Entity> message = MessageBuilder.withPayload(entity)
.setHeader("Message_Header1", "Message_Header1_Value")
.setHeader("Message_Header2", "Message_Header2_Value")
.build();
outbound.send(message);
}
}
-- Application main class
public class App {
public static void main( String[] args )
{
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:7_applicationContext.xml" );
SendMessage sendMessage = (SendMessage)applicationContext.getBean( "sendMessage", SendMessage.class);
for(int i=0;i<10;i++){
sendMessage.send("This is Message Content");
}
applicationContext.registerShutdownHook();
}
}

Related

Hibernate Performance is slow: Spring batch & Azure SQL Server

I have a spring batch application that uses Azure SQL server as a backend, I am using Hibernate to update the database.
I am reading the data from CSV file using FlatfileReader & writing into Azure SQL Server using ItemWriter as mentioned below
public class StoreWriter implements ItemWriter<List<Store>> {
Logger logger = Logger.getLogger(StoreWriter.class);
private HibernateItemWriter<Store> hibernateItemWriter;
public StoreWriter(HibernateItemWriter<Store> hibernateItemWriter) {
this.hibernateItemWriter = hibernateItemWriter;
}
#Override
public void write(List<? extends List<Store>> items) throws Exception {
for (List<Store> Store : items) {
hibernateItemWriter.write(Store);
}
logger.info(String.format("Store Processing Completed %s", new LocalDateTime()));
}
}
Below is my Hibernate configuration
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager" lazy-init="true">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2012Dialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">false</prop>
<!-- <prop key="hibernate.hbm2ddl.auto">update</prop> -->
</props>
</property>
</bean>
<bean class="org.springframework.batch.core.scope.StepScope" />
<!-- DATA SOURCE -->
<bean id="demoDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url" value="jdbc:sqlserver://demo.database.windows.net:1433;database=sqldb;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;" />
<property name="username" value="user1" />
<property name="password" value="p#ssword1" />
</bean>
What I observe is that it is processing only 360 records per minute, is there a way to increase the performance?
Here is the Hibernate stats:
For 1 record
For 3 records

Spring Integration Webservices

I am very new at spring integration, I am trying to convert following code into spring integration code but I am not able to send the request properly.
I really don't know what I am doing wrong and what to do, actually the task is to split the XML which are sending to webservices then get the response back from it and then aggregate to make it one XML.
Normal code:
connection = (HttpURLConnection) validateServer.openConnection();
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
String parameters = "";
if (isMultipleVal) {
parameters = ADD_FUNCTION2
+ URLEncoder.encode(getxmldatalist, "UTF-8");
} else {
parameters = ADD_FUNCTION
+ URLEncoder.encode(getxmldatalist, "UTF-8");
}
LOG.info("parameters:" + parameters);
System.out.println("In client parameters "+parameters);
byte[] parameterAsBytes = parameters.getBytes();
System.out.println("Parameters as bytes "+parameterAsBytes);
connection.setRequestProperty(CONTENT_LENGTH,String.valueOf(parameterAsBytes.length));
OutputStream oStream = connection.getOutputStream();
oStream.write(parameterAsBytes, 0, parameterAsBytes.length);
oStream.flush();
oStream.close();
Spring Integration code:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-xml="http://www.springframework.org/schema/integration/xml"
xmlns:int-ws="http://www.springframework.org/schema/integration/ws"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int-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/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/stream http://www.springframework.org/schema/integration/stream/spring-integration-stream.xsd
http://www.springframework.org/schema/integration/xml http://www.springframework.org/schema/integration/xml/spring-integration-xml.xsd
http://www.springframework.org/schema/integration/ws http://www.springframework.org/schema/integration/ws/spring-integration-ws.xsd
http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd">
<int:channel id="requestGatewayChannel"/>
<int:gateway id="serviceGateway" service-interface="xxx.xxx.xxx" default-request-channel="requestGatewayChannel" default-reply-channel="replyGatewayChannel" />
<int:channel id="replyGatewayChannel"/>
<int:splitter ref="rootSplitter" input-channel="requestGatewayChannel" output-channel="splitterOutputChannel" method="splitRoot"/>
<int:channel id="splitterOutputChannel"/>
<bean id="rootSplitter" class="xxx.xxx.xxx.VehicleRootSpliter" />
<int-xml:marshalling-transformer id="marshaller" input-channel="splitterOutputChannel" output-channel="marshallerOutputChannel" marshaller="marshallerUnmarshaller" result-type="StringResult" />
<int:channel id="marshallerOutputChannel"></int:channel>
<int:object-to-string-transformer input-channel="marshallerOutputChannel" output-channel="stringOutputChannel"></int:object-to-string-transformer>
<int:channel id="stringOutputChannel"></int:channel>
<int:transformer id="dataTransformer" input-channel="stringOutputChannel" output-channel="dataTransformerOutputChannel" ref="xmlToEncode" method="dataTransformer"></int:transformer>
---To encode the string of xml using custom transformer---
<int:channel id="dataTransformerOutputChannel"></int:channel>
<bean id="xmlToEncode" class="xxx.xxx.xxx.DataTransformer"></bean>
<int:header-enricher default-overwrite="true" input-channel="dataTransformerOutputChannel" output-channel="enricherOutputChannel">
<int:header name="Content_length" ref="headerBean" method="valueLength"></int:header>
</int:header-enricher>
<int:channel id="enricherOutputChannel"></int:channel>
<bean id="headerBean" class="xxx.xxx.xxx.DataTransformer"></bean>
<int-http:outbound-gateway url="${toms.ws.url}" request-channel="enricherOutputChannel" reply-channel="httpOutputChannel"
header-mapper="headerMapper" http-method="POST"
expected-response-type="java.lang.String"/>
<bean id="headerMapper" class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
<property name="outboundHeaderNames" value="HTTP_REQUEST_HEADERS, Content_length"></property>
<property name="userDefinedHeaderPrefix" value=""></property>
</bean>
<int:channel id="httpOutputchannel"></int:channel>
<int:service-activator input-channel="httpOutputChannel" ref="webserviceActivator" method="checkerWeb"></int:service-activator>
<bean id="webserviceActivator" class="xxx.xxx.xxx"></bean>
<bean id="marshallerUnmarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller" >
<property name="classesToBeBound">
<list>
<value>com.xxx.xxx.xxx.VRoot</value>
</list>
</property>
</bean>
</beans>

issue in spring xd cluster when deploying my module

I have a module s3-puller which pulls file from was s3 .In the production i am facing some issue when i try to create a stream.But local single node it works fine and i tried to set up 3 node cluster and 1 admin node in local it works fine.
Below is my application context
<?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:int-aws="http://www.springframework.org/schema/integration/aws"
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/integration/aws http://www.springframework.org/schema/integration/aws/spring-integration-aws-1.0.xsd">
<int:poller fixed-delay="${fixed-delay}" default="true"/>
<bean id="credentials" class="org.springframework.integration.aws.core.BasicAWSCredentials">
<property name="accessKey" value="${accessKey}"/>
<property name="secretKey" value="${secretKey}"/>
</bean>
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>dms-aws-s3-nonprod.properties</value>
</property>
</bean>
<bean id="clientConfiguration" class="com.amazonaws.ClientConfiguration">
<property name="proxyHost" value="${proxyHost}"/>
<property name="proxyPort" value="${proxyPort}"/>
<property name="preemptiveBasicProxyAuth" value="false"/>
</bean>
<bean id="s3Operations" class="org.springframework.integration.aws.s3.core.CustomC1AmazonS3Operations">
<constructor-arg index="0" ref="credentials"/>
<constructor-arg index="1" ref="clientConfiguration"/>
<property name="awsEndpoint" value="s3.amazonaws.com"/>
<property name="temporaryDirectory" value="${temporaryDirectory}"/>
<property name="awsSecurityKey" value="${awsSecurityKey}"/>
</bean>
<!-- aws-endpoint="https://s3.amazonaws.com" -->
<int-aws:s3-inbound-channel-adapter aws-endpoint="s3.amazonaws.com"
bucket="${bucket}"
s3-operations="s3Operations"
credentials-ref="credentials"
file-name-wildcard="${file-name-wildcard}"
remote-directory="${remote-directory}"
channel="splitChannel"
local-directory="${local-directory}"
accept-sub-folders="false"
delete-source-files="true"
archive-bucket="${archive-bucket}"
archive-directory="${archive-directory}">
</int-aws:s3-inbound-channel-adapter>
<int:splitter input-channel="splitChannel" output-channel="output"
expression="T(org.apache.commons.io.FileUtils).lineIterator(payload)"/>
<int:channel id="output"/>
my Application.java
package com.capitalone.api.dms.main;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ImportResource;
#SpringBootApplication
#ImportResource("classpath:config/applicationContext.xml")
public class Application {
public static void main(String[] args) throws Exception {
new SpringApplicationBuilder(Application.class)
.web(false)
.showBanner(false)
.properties("security.basic.enabled=false")
.run(args);
}
}
I am getting below exception when i try to create a basic stream
module upload --file aws.jar --name aws-s3-options --type source
stream create feedTest91 --definition "aws-s3-options | log" --deploy
I get below exception
DeploymentStatus{state=failed,error(s)=org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'objectNameProperties' defined in null: Could not resolve placeholder 'xd.module.sequence' in string value "${xd.module.sequence}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'xd.module.sequence' in string value "${xd.module.sequence}" at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:211) at org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.processProperties(PropertyPlaceholderConfigurer.java:222) at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:86) at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:265)
from the source code i see that its loaded by jmx mbean file of xd and loaded by below java file
https://github.com/spring-projects/spring-xd/blob/6923ee8705bd9c2c58ad73120724b8b87c5ba37d/spring-xd-dirt/src/main/resources/META-INF/spring-xd/plugins/jmx/mbean-exporters.xml
https://github.com/spring-projects/spring-xd/blob/e9ce8e897774722c1e61038817ebd55c5cf0befc/spring-xd-dirt/src/main/java/org/springframework/xd/dirt/plugins/MBeanExportingPlugin.java
Solution :
I am planning to inject them from my s3 module .Is it right way to do please let me know what should be the values?
<context:mbean-export />
<int-jmx:mbean-export object-naming-strategy="moduleObjectNamingStrategy" />
<util:properties id="objectNameProperties">
<prop key="group">${xd.group.name}</prop>
<prop key="label">${xd.module.label}</prop>
<prop key="type">${xd.module.type}</prop>
<prop key="sequence">${xd.module.sequence}</prop>
</util:properties>
<bean id="moduleObjectNamingStrategy"
class="org.springframework.xd.dirt.module.jmx.ModuleObjectNamingStrategy">
<constructor-arg value="xd.${xd.stream.name:${xd.job.name:}}" />
<constructor-arg ref="objectNameProperties" />
</bean>
That property should be automatically set up by the ModuleInfoPlugin.
This is the second time someone has said that property is missing somehow.
I have opened a JIRA Issue.

Dynamically getting sftp connection properties from database and get sftpConnectionFactory in spring integration

I have requirement that I should get SFTP connection properties from database and create sftpSessionFactory by using properties comes from the database dynamically.
Below ${sftp.host}, ${sftp.port}, ${sftp.user} and ${sftp.password} properties values should come from database.
<bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="${sftp.host}"/>
<property name="port" value="${sftp.port}" />
<property name="user" value="${sftp.user}"/>
<property name="password" value="${sftp.password}"/>
</bean>
How to create SFTP connection by getting properties from database?
web.xml
<!-- Loads the Spring application contexts -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:context/application-context-*.xml
</param-value>
</context-param>
application-context-services.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:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<context:annotation-config />
<context:component-scan base-package="com.abc.xyz.batch.services" />
<bean id="freemarkerConfiguration"
class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
<property name="preferFileSystemAccess" value="false" />
<property name="templateLoaderPath" value="classpath:templates/" />
<property name="freemarkerSettings">
<props>
<prop key="default_encoding">UTF-8</prop>
<prop key="locale">ar_AR</prop>
</props>
</property>
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="cacheSeconds" value="0" />
<property name="defaultEncoding" value="UTF-8" />
<property name="useCodeAsDefaultMessage" value="true" />
<property name="basenames">
<list>
<value>classpath:validation-messages</value>
</list>
</property>
</bean>
EnvironmentLookupService.java
#Service
public class EnvironmentLookupService {
private static final Logger logger = LoggerFactory.getLogger(EnvironmentLookupService.class);
#Autowired
#Qualifier("transactionManager")
private PlatformTransactionManager txManager;
#Autowired
private ConfigDao configDao;
private final Map<String, String> config = new HashMap<String, String>();
/**
* Loads all lookups used in xyz from database
*/
#PostConstruct
public void loadLookupData() {
logger.info("loading lookup cache");
new TransactionTemplate(txManager).execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
loadLookups();
}
});
// initialize();
}
/**
* Refreshes the lookup caches
*/
#Scheduled(cron = "${core.lookups.cache.refresh.cron}")
public void refreshCache() {
loadLookupData();
}
/**
* Loads all lookups from database
*/
protected void loadLookups() {
final List<IConfig> list = configDao.findAll();
for (final IConfig property : list) {
config.put(property.getKey(), property.getValue());
}
}
/**
* Will return configuration value for the key provided
*
* #param key
* #return String
*/
public String retriveConfigValue(EConfig key) {
return config.get(key.getValue());
}
}
DynamicSftpChannelResolver.java
#Service
public class DynamicSftpChannelResolver {
#Autowired
private EnvironmentLookupService lookupService;
ConfigurableApplicationContext confAppContext;
#PostConstruct
public void setEnvironmentForSftpConnection() {
confAppContext = new ClassPathXmlApplicationContext("classpath*:context/*integration-context.xml");
final StandardEnvironment stdEnvironment = new StandardEnvironment();
final Properties props = new Properties();
props.setProperty(EConfig.SFTP_HOST.getValue(), lookupService.retriveConfigValue(EConfig.SFTP_HOST));
props.setProperty(EConfig.SFTP_PORT.getValue(), lookupService.retriveConfigValue(EConfig.SFTP_PORT));
props.setProperty(EConfig.SFTP_USER.getValue(), lookupService.retriveConfigValue(EConfig.SFTP_USER));
props.setProperty(EConfig.SFTP_PASSWORD.getValue(), lookupService.retriveConfigValue(EConfig.SFTP_PASSWORD));
final PropertiesPropertySource propPropertySource = new PropertiesPropertySource("sftp", props);
stdEnvironment.getPropertySources().addLast(propPropertySource);
confAppContext.setEnvironment(stdEnvironment);
}
}
spring-integration-context.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:int-file="http://www.springframework.org/schema/integration/file"
xmlns:int-sftp="http://www.springframework.org/schema/integration/sftp"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:int-ws="http://www.springframework.org/schema/integration/ws"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/integration/ws http://www.springframework.org/schema/integration/ws/spring-integration-ws.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/sftp http://www.springframework.org/schema/integration/sftp/spring-integration-sftp.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<tx:annotation-driven transaction-manager="transactionManager" />
<context:property-placeholder />
<!-- <context:property-placeholder ignore-unresolvable="true" location="classpath:*.properties"/> -->
<bean id="sftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="${sftp.host}"/>
<property name="port" value="${sftp.port}" />
<property name="user" value="${sftp.user}"/>
<property name="password" value="${sftp.password}"/>
</bean>
<int:channel id="ch.file.download"></int:channel >
<int:channel id="ch.file.type.access"></int:channel >
<int:channel id="ch.file.type.excel"></int:channel >
<int:channel id="ch.file.type.csv"></int:channel >
<int:channel id="ch.file.validated"></int:channel>
<int-sftp:inbound-channel-adapter id="sftp.file.client.download"
session-factory="sftpSessionFactory" channel="ch.file.download"
auto-create-local-directory="true" remote-directory="${sftp.remote.directory}"
local-filename-generator-expression="#this"
temporary-file-suffix=".downloading"
local-directory="${sftp.local.directory}"
>
<int:poller fixed-rate="1000"/>
</int-sftp:inbound-channel-adapter>
After doing all the above sftpSessionFactory is not getting created. no exception also.
I guest *integration-conotext.xml is not loading.
Can you please suggest me ,what's going wrong ?.
Your web.xml has an option to load any XML config by pattern classpath*:context/application-context-*.xml. But the Spring Integration config name looks like spring-integration-context.xml.
From my perspective it doesn't matter and it would be better to use <context:import> on the matter.
From other side, pleas, take a look to the new DelegatingSessionFactory feature since Spring Integration 4.2 which allows to retrieve the target SessionFactory at runtime against the requestMessage.
And one more point. I use Commons Configuration to load Properties from DataBase and use the last one for the properties-placeholder:
<bean id="databaseConfiguration" class="org.apache.commons.configuration.DatabaseConfiguration">
<constructor-arg ref="dataSource"/>
<constructor-arg value="PROPERTIES"/>
<constructor-arg value="PROPERTY"/>
<constructor-arg value="PROPERTYVALUE"/>
</bean>
<bean id="propertiesFromDB" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
p:staticMethod="org.apache.commons.configuration.ConfigurationConverter.getProperties"
p:arguments-ref="databaseConfiguration"/>
<context:property-placeholder properties-ref="propertiesFromDB"/>
If that would be enough for you to load them from DB only once at startup.

Spring integration xml file errors out on reactor StringUtils

I have a spring integration sftp flow which I load as a child context within my overall application context. This is based on the dynamic ftp SI example. My integration flow has nothing about reactor or streams in it. Its a simple flow with one direct channel connected with a sftp-outbound-gateway to transfer files to a sftp server. I can even run units tests and the flow work fine (is able to transfer files) but when I run an integration test which loads the full parent application and then initializes the child context with this sftp flow loaded in it, it throws an error for not being able to find reactor/StringUtils class.
The reason for that seems to be that spring-integration-sftp loads reactor jars as transient deps but since my parent application already has a different version of reactor loaded in the classpath I excluded the reactor-core from spring integration dep. If I dont exclude the reactor-core from spring-integration then there are some version conflicts so I would like to exclude it.
reactorVersion = 2.0.0.M2
compile("io.projectreactor:reactor-core:$reactorVersion")
compile "io.projectreactor.spring:reactor-spring-context:$reactorVersion"
compile("org.springframework.integration:spring-integration-sftp") {
exclude module: "reactor-core"
}
Initializing the SI flow
context = new ClassPathXmlApplicationContext(new String[] { "classpath:adapters/"
+ sink.getConfigurationFile() }, false);
setEnvironment(context, sink);
context.setParent(parentContext);
context.refresh();
context.registerShutdownHook();
The error when i ran the integration test
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [adapters/sftp.xml]; nested exception is java.lang.NoClassDefFoundError: reactor/util/StringUtils
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:414)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181)
Finally the SI flow
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-sftp="http://www.springframework.org/schema/integration/sftp"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/sftp http://www.springframework.org/schema/integration/sftp/spring-integration-sftp.xsd">
<import resource="common.xml" />
<bean id="sftpSessionFactory"
class="org.springframework.integration.file.remote.session.CachingSessionFactory">
<constructor-arg ref="defaultSftpSessionFactory" />
</bean>
<bean id="defaultSftpSessionFactory"
class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="${sink.host}" />
<property name="port" value="22" />
<property name="privateKey" value="${sink.private.key}" />
<property name="privateKeyPassphrase" value="${sink.private.key.phrase}" />
<property name="user" value="${sink.user}" />
<property name="password" value="${sink.pass}" />
</bean>
<int:channel id="input" />
<int-sftp:outbound-channel-adapter
auto-startup="true" session-factory="sftpSessionFactory" channel="input"
remote-directory="${sink.path}" remote-filename-generator-expression="headers['remote_file_name']">
<int-sftp:request-handler-advice-chain>
<bean
class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice">
<property name="onSuccessExpression" value="payload" />
<property name="successChannel" ref="successChannel" />
<property name="onFailureExpression" value="payload" />
<property name="failureChannel" ref="failureChannel" />
<property name="trapException" value="true" />
</bean>
</int-sftp:request-handler-advice-chain>
</int-sftp:outbound-channel-adapter>
<int:channel id="successChannel" />
<int:service-activator input-channel="successChannel"
ref="completionHandler" method="handle" />
<int:channel id="failureChannel" />
<int:service-activator input-channel="failureChannel"
ref="failureHandler" method="handle" />
Updating to add my reactor configuration
#Configuration
#EnableReactor
public class ReactorConfiguration {
static {
Environment.initializeIfEmpty().assignErrorJournal();
}
#Bean
public EventBus eventBus() {
return EventBus.config().env(Environment.get()).dispatcher(Environment.SHARED).get();
}
#Bean
public IdGenerator randomUUIDGenerator() {
return new IdGenerator() {
#Override
public UUID generateId() {
return UUIDUtils.random();
}
};
}
}
Gradle currently doesn't do a great job excluding dependencies of transitive dependencies.
It's not spring-integration-sftp that pulls in reactor, it's spring-integration-core.
Try explicitly excluding via that.
We have removed the hard transitive reactor dependency in SI 4.2 (but it's not released yet).
The spring team has created a gradle plugin that might help.

Resources