Trifork Blog

Axon Framework, DDD, Microservices

Connecting to FTP server with Spring Integration

July 21st, 2010 by
|

For one of our project I needed to read zip files from a FTP server and import the content in a system. In this post I will explain how I have used the Spring Integration to connect with a FTP server and retrieve Zip files.

FTP Client Factory

As the FTP extension for Spring Integration has no official release yet, I have used the latest build which can be found at the Spring Integration Adapters site.

The extension provides a client factory that allows you to connect with a client. The class I have used is the DefaultFTPClientFactory which implements the interface FTPClientFactory.

When you have copied these files to your own project, you can configure a client by using the following code:

    <bean id="defaultClient" class="nl.jteam.importer.ftp.DefaultFTPClientFactory">
        <property value="${ftp.remotedir}" name="remoteWorkingDirectory"></property>
        <property value="${ftp.username}" name="username"></property>
        <property value="${ftp.password}" name="password"></property>
        <property value="${ftp.port}" name="port"></property>
        <property value="${ftp.host}" name="host"></property>
    </bean>

Reading the files

Now that the client is configured, we can read the files from the FTP server. In the method getFilesFromFTPClient() we get a FTPClient by calling the getClient() method on the client factory. The client API provides you with the possibility to retrieve, delete, rename or store files. The API offers a lot more, but I won’t discuss all the methods here. In our case we wanted to retrieve only zip files. As the client does not provide you the functionality to retrieve files from a specific extension, you have to do it yourself by, for example, checking the extension of each file.

Don’t forget to close the connection with the FTP client once you are done with handling files.

Because we want use Spring Integration to send the files to the class that handles the zip files, we create a Message with the list of zip files.

The (partial) code of the FTPInboundAdapter class:

    public FTPInboundAdapter(FTPClientFactory clientFactory, String localTmpDirName) throws IOException {
        Assert.notNull(localTmpDirName, "The directory name to write the files to can not be null");
        this.clientFactory = clientFactory;
        localDirectory = ImportUtils.ensureTempDirExists(localTmpDirName);
    }

    public Message<list><file>&gt; getFilesFromFTPClient() {
        FTPClient client = null;
        try {
            client = clientFactory.getClient();

            List<file> localZipFiles = retrieveRemoteZipFiles(client);

            return MessageBuilder.withPayload(localZipFiles).build();
        } catch (IOException e) {
            throw new MessagingException("Problem occurred while trying to retrieve files.", e);
        } finally {
            closeFtpClient(client);
        }
    }

    private void closeFtpClient(FTPClient client) {
        if (client != null &amp;&amp; client.isConnected()) {
            try {
                client.disconnect();
            } catch (IOException e) {
                logger.warn("Error occurred when disconnection FTP client", e);
            }
        }
    }

The configuration code for the adapter:

    <bean id="ftpInboundAdapter" class="nl.jteam.importer.ftp.FTPInboundAdapter">
        <constructor-arg ref="defaultClient" />
        <constructor-arg value="someLocalDirectory" />
    </bean>

Checking the FTP directory

If you want Spring Integration to check the FTP server on a regular base for new files, you can wire up an inbound channel adapter with a cron expression like this:

    <si:inbound-channel-adapter id="zipInboundChannelAdapter" ref="ftpInboundAdapter" method="getFilesFromFTPClient" channel="zipFilesChannel">
        <si:poller max-messages-per-poll="1">
            <si:cron-trigger expression="0 0/5 * ? * *" />
        </si:poller>
    </si:inbound-channel-adapter>

The channel attribute of the inbound channel adapter specifies the output channel. So in our case this will be the message with the list of zip files that is put onto this channel. This channel can then be used to send the message to wherever you want.

As you could see, it was relatively easy to connect with a FTP server and retrieve the files. I hope this post helped you in setting up your own FTP connection with Spring Integration. All that rests us is waiting for official release of the Spring Integration Adapters.

4 Responses

  1. July 22, 2010 at 08:51 by Iwein Fuld

    Nice to see you managed to put my doodles to some good use. Do you think I should commit this new client factory to the adapter project?

  2. July 22, 2010 at 09:29 by Roberto van der Linden

    Hi Iwein,

    I have used your Client Factory 🙂 This is already in the adapter project right? If it is not in the adapter project, then you should definitely commit it 🙂

  3. February 19, 2012 at 09:46 by says

    sample file ??

  4. March 22, 2012 at 12:43 by Gabriel Ciuloaica

    Hi,

    Is there any way to configure the FTP Inbound Adapter to allow integration with Stream Adapter? I do not want to store the files locally from a FTP server, just to transform them and push to a cache.

    Thanks,
    Gabi