Uploading files directly to specific folder in ftp server using spring spring - ftp

I have, I suppose, really newbie question but the fact is I'm newbie in spring framework.
How can I upload files to, for example 'upload' folder loceted in root directory of my ftp server?
I have tried this:
My application context file:
<bean id="ftpClientFactory"
class="org.springframework.integration.ftp.session.DefaultFtpSessionFactory">
<property name="host" value="127.0.0.1"/>
<property name="username" value="test"/>
<property name="password" value="test"/>
<property name="clientMode" value="0"/>
<property name="fileType" value="2"/>
<property name="bufferSize" value="10000"/>
</bean>
<int:channel id="ftpChannel"/>
<int-ftp:outbound-channel-adapter id="outFtpAdapter"
channel="ftpChannel"
session-factory="ftpClientFactory"
remote-directory="/Users/test"/>
and my java code:
ConfigurableApplicationContext context =
new FileSystemXmlApplicationContext("/src/citrus/resources/citrus-context.xml");
MessageChannel ftpChannel = context.getBean("ftpChannel", MessageChannel.class);
File file = new File("/Users/test/test.txt");
Message<File> fileMessage = MessageBuilder.withPayload(file).build();
ftpChannel.send(fileMessage);
context.close();
But this example upload files to root directory.
Thanks in advance.

I've just tested it and work well:
<int-ftp:outbound-channel-adapter
id="sendFileToServer"
auto-create-directory="true"
session-factory="ftpSessionFactory"
remote-directory="/Users/test"/>
Where my FTP server is an embedded one and its root is:
[MY_USER_HOME]\Temp\junit7944189423444999123\FtpServerOutboundTests\
So the file is stored in the dir:
[MY_USER_HOME]\Temp\junit7944189423444999123\FtpServerOutboundTests\Users\test\
It is with the latest Spring Integration version.
Which is your version?

Using FTPClient upload MultipartFiles to apache FTP server
useful repo
Hope this help for future search.

Related

How to setup or use sftp cachingSessionFactory?

I tried to follow the spring integration SFTP adapter to setup the data feed from local directory to remote site with sftp outbound channel adapter. The feed basically works fine.
But I would like to use cached connection. With the official
guideline for cachingSessionFactory setup:
http://docs.spring.io/spring-integration/reference/html/sftp.html#sftp-session-caching
<bean id="sftpSessionFactory"
class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="localhost"/>
</bean>
<bean id="cachingSessionFactory"
class="org.springframework.integration.file.remote.session.CachingSessionFactory">
<constructor-arg ref="sftpSessionFactory"/>
<constructor-arg value="10"/>
<property name="sessionWaitTimeout" value="1000"/>
</bean>
But seems even if I have the sftp-session-caching defined, the sftp session will be closed once a file is sent successfully?
Anyone has experience on this?

SFTP Spring Integrations rm command

I am wondering if someone can assist, I know I am doing this wrong and I'm tearing my hair out. My goal is to delete any files with a .txt extension in a remote directory using Spring Integrations SFTP in a Spring Batch job. It is my understanding that I do not have to ls remote files to remove them and can just issue an rm command on *.txt for a given directory however I may be incorrect?
I have the following SFTP configuration
<bean id="sftpSessionFactory"
class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="${host}" />
<property name="port" value="${port}" />
<property name="user" value="${user}" />
<property name="privateKey" value="file:${privateKey}" />
<property name="password" value="${password}" />
</bean>
<int:channel id="rmChannel"/>
<int-sftp:outbound-gateway
session-factory="sftpSessionFactory"
request-channel="rmChannel"
remote-file-separator="/"
command="rm"
expression="headers['file_remoteDirectory'] + headers['file_remoteFile']" />
<bean id="cleanRemoteDirectoryTasklet" class="com.example.batch.job.integration.SFTPRmTasklet" scope="step">
<property name="channel" ref="rmChannel" />
<property name="filePatternToDelete" value="*.txt" />
<property name="targetDirectory" value="${remoteDirectory}"/> // edit removed 'file:' notation
</bean>
I believe I am OK to this point an my problem is executing this flow in the Java implementation in SFTPRmTasklet, I'm not sure how to construct the message to initiate the sftp remove. Currently I have something like this simply to kick it off I know that my payload is wrong.
Message<String> rmRequest = MessageBuilder.withPayload("/my/target/dir")
.setHeader("file_remoteDirectory", targetDirectory)
.setHeader("file_remoteFile", filePatternToDelete)
.build();
channel.send(rmRequest)
ultimately this yields an exception
org.springframework.integration.MessagingException: org.springframework.core.NestedIOException: Failed to remove file: 2: No such file
UPDATE 1
So I decided to target just one remote file and changed filePatternToDelete to test.txt. After a bit of debugging I realised that AbstractRemoteFileOutBoundGateway was evaluating my remoteFilePath to /my/target/dirtest.txt and remote filename to dirtest.txt, which is obviously not what I wanted so I added a trailing to / to the target directory in my properties file and this sorted out this error great!
I can now delete the file from the remote server as I wished to do however I received an error around no reply-channel so I have added the following channel
<int:channel id="end"/>
and modified my outbound gateway
<int-sftp:outbound-gateway
session-factory="sftpSessionFactory"
request-channel="rmChannel"
reply-channel="end"
remote-file-separator="/"
command="rm"
expression="headers['file_remoteDirectory'] + headers['file_remoteFile']" />
and now get an error around no subscribers for this channel. Progress at least and in case you hadn't guessed I'm pretty new to Spring!
If you are not interested in the result of the rm, set the reply-channel to nullChannel.
It's like /dev/null on unix.

Downloading files from FTP Server where directory changed dynamically

I am using Spring Integration to download/upload files from FTP server.
How can I change remote-directory="/directory Name" dynamically in Spring FTP:Inbound-Channel.
My client will create a folder daily basically in "MM-dd-yy" format and copy all files there.
In "FTP:Inbound-channel" I did not find any way to configure this pattern. I basically have
to hardcord the directory or file names in configuration.
What I want is to set the path programatically. Because some times I need to download all files
from a direcotory or download only a specific file.
I found "remote-directory-expression="'directory'+'/'+ new java.text.SimpleDateFormat('dd-MM-yyyy').format(new java.util.Date())" can be set in FTP:Outbound-channel
is there any such attribute in FTP:InBound-channel
My configuration is like this:
<bean id="ftpClientFactory"
class="org.springframework.integration.ftp.session.DefaultFtpSessionFactory">
<property name="host" value="${host}" />
<property name="port" value="${availableServerPort}" />
<property name="username" value="${userid}" />
<property name="password" value="${password}" />
</bean>
<int-ftp:inbound-channel-adapter id="ftpInbound"
cache-sessions="false" channel="ftpChannel" session-factory="ftpClientFactory"
filename-pattern="*.txt" auto-create-local-directory="true"
delete-remote-files="false" remote-directory="/filedirectory"
local-directory="${local_directory}">
<int:poller fixed-rate="1000" />
</int-ftp:inbound-channel-adapter>
<int:channel id="ftpChannel">
<int:queue />
</int:channel>
I did not find a way to do all the above items.
Please let me know how can I achieve this.
You can't do it with the inbound adapter, but the <ftp:outbound-gateway/> can be used to achieve what you need; described here.
You can either use ls to list the files, followed a <splitter/> and another gateway using get; or you can use the mget command with a file name pattern in the expression.
The FTP sample has an example of using the gateway

Setting properties in Spring

Is there a way to change the properties of a file? I'm trying to run selenium tests in parallel, with Spring and Jetty, so I'm trying to configure the url of the database, the port of the jettyserver and the port of the selenium server. So that I'm able to initialize two or more servers where the tests can run on.
My server.properties file contains this:
jdbc.url=jdbc:hsqldb:hsql://localhost/bibliothouris_scenario
jetty.port=8081
seleniumServer.port=4444
I can read those properties with a PropertyPlaceholderConfigurer, and I need the database URL, jettyport and seleniumserver port to be flexible.
I have declared them like this:
In my applicationContext.xml:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:server.properties</value>
</property>
</bean>
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
In the serverContext.xml file:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:server.properties</value>
</property>
</bean>
<bean class="com.~companyName~.bibliothouris.jetty.JettyServer" init-method="start" destroy-method="stop">
<constructor-arg value="${jetty.port}" />
<constructor-arg ref="dataSource" />
</bean>
<bean class="org.openqa.selenium.server.SeleniumServer" init-method="start" destroy-method="stop">
<constructor-arg>
<bean class="org.openqa.selenium.server.RemoteControlConfiguration">
<property name="port" value="${seleniumServer.port}" />
<property name="singleWindow" value="true" />
<property name="timeoutInSeconds" value="10" />
</bean>
</constructor-arg>
</bean>
<bean class="com.thoughtworks.selenium.DefaultSelenium" init-method="start" destroy-method="stop" lazy-init="true">
<constructor-arg>
<bean class="com.thoughtworks.selenium.HttpCommandProcessor">
<constructor-arg value="localhost" />
<constructor-arg value="${seleniumServer.port}" />
<constructor-arg value="*firefox c:/~companyname~/firefox/firefox.exe" />
<constructor-arg value="http://localhost:${jetty.port}" />
</bean>
</constructor-arg>
</bean>
When I change the data in server.properties the selenium tests run on the right servers with the right ports, without failures.
So now I'm looking for a method to change the properties in the server.properties file.
Kind regards and thanks in advance
I solved this by having a flag in my build process (I'm using Maven) that chose which property file to include in the final war. This way you can include different artifacts (different property files) with different properties without having to mess with the low level property support of Spring.
If you do need to do this is Spring only, I would recommend going for a Java based configuration, where you can get and set the properties by in code not in XML.
Is there a way to change the
properties of a file?
No, but you could solve this in the following ways.
Split the properties into jdbc.properties (for applicationContext.xml) and test.properties (for serverContext.xml)
override server.properties via a src/test/resources resource
use system properties in addition to server.properties (use PropertyPlaceholderConfigurer.setSystemPropertiesMode for this)
Thanks for the help guys, without your info, I couldn't find my own solution. Here it is:
try {
Properties props = new Properties();
FileInputStream fileInputStream = new FileInputStream(
"C:\\~CompanyName~\\workspace\\bibliothouris\\infrastructure\\src\\main\\resources\\server.properties");
props.load(fileInputStream);
fileInputStream.close();
props.setProperty("seleniumServer.port", "4445");
FileOutputStream fileOutputStream = new FileOutputStream(
"C:\\~CompanyName~\\workspace\\bibliothouris\\infrastructure\\src\\main\\resources\\server.properties");
props.store(fileOutputStream, "");
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
I've wrote this piece of code in a testclass, now I have to create a method of it, which takes a few arguments (the URL, jettyport and seleniumport). And I have to change the path to a relative one.
Thanks for the help!

Can a local glassfish on windows be configured to work with a remote db2 on UNIX?

I am trying to make db2 work in glassfish with no luck at all. I've read the documentation, but no matter what I do I end up stuck with an error when I do a ping. I put the jar files for the db2 driver and connectivity in the classpath prefix, added them to the lib directory of the domain and no go. What am I doing wrong? Thank you for your time.
You didn't mention anything about the datasource creation. Did you create a datasource ?
Here is how you can create one, in the domain.xml file in conf dir of your domain.
<jdbc-resource enabled="true" jndi-name="jdbc/<YOUR_DS_NAME_HERE>" object-type="user" pool-name="<YOUR_POOL_NAME_HERE>">
<description><DESCRIPTION></description>
</jdbc-resource>
<jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="com.ibm.db2.jcc.DB2ConnectionPoolDataSource" fail-all-connections="true" idle-timeout-in-seconds="140" is-connection-validation-required="true" is-isolation-level-guaranteed="false" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="YOUR_POOL_NAME_HERE>" non-transactional-connections="false" pool-resize-quantity="32" res-type="javax.sql.ConnectionPoolDataSource" statement-timeout-in-seconds="-1" steady-pool-size="0" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
<description><YOUR_POOL_NAME_HERE_DESCRIPTION></description>
<property name="user" value="<USERNAME>"/>
<property name="password" value="<PASSWORD>"/>
<property name="portNumber" value="<PORTNUMBER>"
<property name="databaseName" value="DATABASE_NAME"/>
<property name="serverName" value="<SERVER_NAME>"/>
<property name="driverType" value="4"/>
</jdbc-connection-pool>
You can also copy the jar files in the $GLASSFISH_HOME/lib dir.

Resources