Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

FTP Helper Class in MuleSoft

DZone's Guide to

FTP Helper Class in MuleSoft

This tutorial will show you how to ass the FTP helper class to your Mule flows for cases when the source of your application is not the source of the flow.

· Integration Zone ·
Free Resource

The Future of Enterprise Integration: Learn how organizations are re-architecting their integration strategy with data-driven app integration for true digital transformation.

The FTP connector is used in MuleSoft to read, write, and perform all file operations, but there is a problem with the FTP connector that it only reads from FTP if it is put in the source (triggering point of flow) of the flow. But in a case when the source of your application is something else, then the FTP helper class comes into the picture.

Prerequisites

This document assumes that you are familiar with FTP operations and you know how to make a project in MuleSoft.

How to Use FTP Helper

Add FTP Helper Class

  • Create a project with the name “readfromftp.”
  • Right-click the src\main\app folder under the readfromftp application and select New->Package.
  • Give it a name, e.g. com.custom.utils, and click Finish.
  • In the package explorer, you will be able to see the com.utils package under the src\main\app folder.
  • Right-click the newly created package, com.utils, and select New->File.
  • Give it name with a .groovy extension as “FtpHelper.groovy” and click Finish.
  • Anypoint Studio will open the newly created file; paste the code given below into it.
package com.custom.util

import java.io.ByteArrayOutputStream
import java.io.FileOutputStream
import java.io.IOException

import org.apache.commons.net.ftp.FTPClient
import org.apache.commons.net.ftp.FTPFile
import org.apache.commons.net.ftp.FTPReply
import org.slf4j.Logger
import org.slf4j.LoggerFactory

class FtpHelper {
    String server
    String user
    String password
    Boolean passiveMode
    int connectTimeout
    int dataTimeout

    def LOG = LoggerFactory.getLogger(FtpHelper.class.name)

    FtpHelper(String server, String user, String password, Boolean passiveMode = false, int connectTimeout = 300000, int dataTimeout = 300000) {
        this.server = server
        this.user = user
        this.password = password
        this.passiveMode = passiveMode
        this.connectTimeout = connectTimeout
        this.dataTimeout = dataTimeout
    }

    def connect(Closure closure) {
        def client = new FTPClient()
        client.setConnectTimeout(connectTimeout)
        client.setDataTimeout(dataTimeout)
        def result = null

        try {
            LOG.info("Connecting to FTP " + server + "...")
            client.connect(server)

            if (FTPReply.isPositiveCompletion(client.replyCode)) {
                LOG.info("Connected successfully. Logging in user " + user + "...")

                if (client.login(user, password)) {
                    LOG.info("Login success.")

                    if (passiveMode)
                        client.enterLocalPassiveMode()

                    // Call closure
                    result = closure.call(client)

                    LOG.info("Logging out...")
                    if (client.logout()) {
                        LOG.info("Logged out.")
                    }
                } else {
                    LOG.warn("Login fail. " + client.replyString)
                }
            } else {
                LOG.warn("Connection failure. " + client.replyString)
            }
            client.disconnect()
        } catch (e) {
            LOG.warn("Error occurred during FTP process. " + e.message)
        }

        return result
    }

    private def fileExists(client, path, fileName) {
        LOG.info("Checking " + path + " path for " + fileName + "...")
        def files = client.listFiles(path)
        LOG.info("Files found on server: " + files.size())
        if (files.find {
                it.name == fileName
            } != null) {
            LOG.info("File found on FTP server: " + fileName)
            return true
        } else {
            LOG.info("File was not found on FTP server.")
            return false
        }
    }

    def readText(path, fileName) {
        def result
        connect {
            client - >
                def fullPath = combine(path, fileName)
            LOG.info("Attempting to read " + fullPath + " from server...")
            if (fileExists(client, path, fileName)) {
                def readStream = new ByteArrayOutputStream()
                LOG.info("Retrieving file from server: " + fileName)
                if (client.retrieveFile(fullPath, readStream)) {
                    LOG.info("File retrieved successfully.")
                    result = readStream.toString()
                    LOG.info("DEBUG: Read file from FTP server, read text is " + result + ".")
                } else {
                    LOG.info("File found but couldn't be read.")
                }
                readStream.close()
            }
        }
        return result
    }

    def readTextMultiple(path, fileNames) {
        def result = []
        connect {
            client - >
                for (def i = 0; i < fileNames.size(); i++) {
                    def fullPath = combine(path, fileNames[i])
                    LOG.info("Attempting to read " + fullPath + " from server...")
                    if (fileExists(client, path, fileNames[i])) {
                        def readStream = new ByteArrayOutputStream()
                        LOG.info("Retrieving file from server: " + fileNames[i])
                        if (client.retrieveFile(fullPath, readStream)) {
                            LOG.info("File retrieved successfully.")
                            result[i] = readStream.toString()
                            LOG.info("DEBUG: Read file from FTP server, read text is " + result[i] + ".")
                        } else {
                            LOG.info("File found but couldn't be read.")
                        }
                        readStream.close()
                    } else {
                        result[i] = null
                    }
                }
        }
        return result
    }

    def delete(path, fileName) {
        connect {
            client - >
                def fullPath = combine(path, fileName)
            LOG.info("Attempting to delete " + fullPath + " from server...")
            if (fileExists(client, path, fileName)) {
                LOG.info("Deleting file from server: " + fileName)
                if (client.deleteFile(fullPath)) {
                    LOG.info("File deleted successfully.")
                } else {
                    LOG.info("File couldn't be deleted.")
                }
            }
        }
    }
    def moveFile(sourcePath, sourceFileName, destinationPath, destinationFileName) {
        boolean result = false;
        connect {
            client - >
                def source = combine(sourcePath, sourceFileName);
            def destination = combine(destinationPath, destinationFileName);
            LOG.info("Checking for file existence on path '" + source + "'");
            if (fileExists(client, sourcePath, sourceFileName)) {
                LOG.info("Attempting to move file from '" + source + "' to '" + destination + "'");
                result = client.rename(source, destination);
                if (result) {
                    LOG.info("File moved successfully.");
                } else {
                    LOG.info("Failed to move file.");
                }
            } else {
                LOG.info("File not found on path '" + source + "'");
            }
        }
        return result
    }
    private static String combine(String path1, String path2) {
        File file1 = new File(path1)
        File file2 = new File(file1, path2)
        return file2.path
    }

    public static void main(String[] args) {
        def ftp = new FtpHelper(
            "FTP path",
            "your user",
            "your password")

        def readText = ftp.readText(
            "your path",
            "file to read")

        println "Read: " + readText

        if (readText != null) {
            ftp.delete(
                "your path",
                "file to read")

            println "Deleted file"
        }
    }
}
  • Save your project
  • The FtpHelper class is added to your project.

How to Use FtpHelper

  • Open the readfromftp.xml file under src\main\app folder.
  • Drag and drop the following processors from the palette to the canvas:
    • Flow
    • Poll (Poll will trigger the application after a specified interval of time)
    • Logger
    • Groovy (script component)
  • Configure Poll to execute after every 1 minute.
    • Click Poll, go to the Mule Properties tab, and you will able to see the Poll properties.
    • From the Time Unit drop-down, select MINUTES.
    • In Frequency, specify 1. These configurations will execute the application every minute.
  • Write code in Groovy to read the file from FTP.
    • Click Groovy, go to the Mule Properties tab, and you will able to see the Groovy properties.
    • Check the Script radio button and write the following code in it. When it executes, it will set the text read from FTP to the payload.     
import com.utils.FtpHelper
def ftpHost = << Ftp Server name >>
    def ftpUsername = << User name >>
    def ftpPassword = << Password >>
    def ftpPassiveMode = true
def ftpConnectTimeout = 12000
def ftpDataTimeout = 12000
def ftpPath = << Folder path >>
    def ftpFilename = << File name >>

    def ftp = new FtpHelper(
        ftpHost,
        ftpUsername,
        ftpPassword,
        ftpPassiveMode,
        ftpConnectTimeout,
        ftpDataTimeout
    )

return ftp.readText(
    ftpPath,
    ftpFilename
)
  • Configure the Logger to log the Payload.
    • Click Logger, go to the Mule Properties tab, and you will able to see the Logger properties.
    • In the Message field, write #[payload] to log the value in the payload.
  • Save the whole application.
  • Execute the application to see the text read from FTP in the console.

You can use the different methods in the same fashion to delete archives and read multiple files from FTP.

Make your mark on the industry’s leading annual report. Fill out the State of API Integration 2019 Survey and receive $25 to the Cloud Elements store.

Topics:
mulesoft ,ftp ,integration ,mule ,anypoint studio

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}