FTPS with Mirth Connect

FTPS with Mirth Connect

The company I work for recently received notification that one of our vendors was moving their SFTP server to a service which only supported WebDAV and FTPS. I've been trying to shift all our data exchanges from a hodge-podge of tools like WinSCP scripts, FTP Voyager, and Mirth Connect 3.X to a new server running Mirth Connect 4.X (Community Edition) and thought, "No problem! Mirth can do so much!"

I was wrong.

Out of the box Mirth Connect can easily handle TCP/IP transmissions, FTP transfers, SMB transfers, MLLP message, and many more BUT IT CANNOT HANDLE FTP OVER SSL/TLS! Mirth's corporate backer, Nextgen Healthcare, offers an extension which adds things like FTPS support, but that extension alone would cost $6,500 per year, which was more money than I wanted to request approval for just to consolidate our data exchanges

Since Mirth Connect is built on Java I was able to take a day to learn to leverage Java packages already included in Mirth Connect into an FTPS channel WITHOUT the plugin. Details are below for anyone in need of a similar solution:

Step 1

You'll need to set up a batch processor for the contents of the FTPS folder you're checking. I chose to use the default option that reads each line as a separate message until a blank line is reached.

return reader.readLine();

Step 2

After setting up the channel to handle batching we need to generate batches (i.e. lists) of files. To this end we need to configure a JavaScript channel reader to poll the FTPS server and output a list of files delimited with carriage returns. Below is a template based on what I came up with:

var ftpsServerAddress = "subdomain.domain.com"
// The next line is unnecessary for port 990 if implicit SSL/TLS is used, but I left this in case a future vendor uses a non-standard port
var ftpsServerPort = 990 
var ftpsUsername = "username"
var ftpsPassword = "password"
var ftpsFolder = "folder/path/on/server"



// A string to hand off to the channel's batch processor
var batchResults = ""


// Parameter sets the connection to use Implicit SSL/TLS which defaults to port 990
var ftps = new Packages.org.apache.commons.net.ftp.FTPSClient(true);

// Even though the Implicit SSL/TLS sets the port to 990 ftpsServerPort was supplied to make code reuse on later projects easier
ftps.connect(ftpsServerAddress, ftpsServerPort);

// Needed to list files
ftps.enterLocalPassiveMode()

ftps.login(ftpsUsername, ftpsPassword)

// Get a list of all the objects in the ftpsFolder
filesList = ftps.listNames(ftpsFolder)

// Concatenate all the files into a string for handling by the batch processor
for each(filename in filesList){
    var byteArrayStream = new java.io.ByteArrayOutputStream();
    // Retrieve the remote file to the previously declared byteArrayStream
    ftps.retrieveFile(ftpsFolder + filename, byteArrayStream)

    file = {
        "filename": filename,
        "b64": FileUtil.encode(byteArrayStream.toByteArray())
    }

    batchResults = batchResults + JSON.stringify(file) + "\n"
}

ftps.disconnect();
return batchResults;

Step 3

Once the Javascript reader was passing file names to the destination, I set up a File Writer channel destination, but needed to retrieve each file found in the Channel Source via a Destination Transformer. Below is the code I used:

var message = JSON.parse(connectorMessage.getRawData())

channelMap.put("filename",message.filename)
channelMap.put("b64",message.b64)

Step 4

The Channel Destination needed to be set up to write the file to a destination folder

After all that I was able to set the File Writer as below and found the files flowing appropriately, saving us $6,500 per year!