Tuesday, June 2, 2009

FtpClient – the advantage of open source code

Yesterday, it was brought to my attention that one of our apps, whose job is to retrieve files via ftp and process them has not been processing files over the past few days (ok, a bit longer and i should have NOT ignored those emails). A look at the stack trace showed the problem was not in our code (even though we HAD just released new code around the time the problem started, whew!).

After investigation, we found the problem is that our customer seems to have changed their configuration of their ftp server. If you ever manually ftp somewhere, you see a line that usually looks something like this:

230 User anonymous logged in.
Remote system type is UNIX.

Well, unfortunately, when we logged in to this customer, the message was a bit different:

230 User anonymous logged in.
Remote system type is XXXXXXXXXXXX.

As it turns out, this line about the remote system type is very important to our ftp library – Jakarta Commons Net’s FtpClient. A look at the source code based on what the stack trace showed that this string determines the parser to be used and if no matches are found, then it throws a ParserInitializationException. The exact error is:

ParserInitializationException: Unknown parser type:

This seems to be the intent of the designer, even though in my opinion if a regular ftp client can access the site, the FtpClient should be able to as well. A bit of looking around on the net did not help, so we set upon a simple and elegant solution.

We subclassed this class, the DefaultFTPFileEntryParserFactory class and added the following code:

public class MyFTPFileEntryParserFactory extends DefaultFTPFileEntryParserFactory
{
public FTPFileEntryParser createFileEntryParser(String key)
{
if (key.equals("XXXXXXXXXXXX")) {
key = FTPClientConfig.SYST_UNIX;
}
return super.createFileEntryParser(key);
}
}



Now, the only issue left was to tell the application to use our parser instead. There are two ways to do this. One is to use listFiles and pass the parser, or in our case it was easier when creating the FtpClient (in Spring of course), to add the setter for the ParserFactory to use our class.

This is a great example of the convenience of using Spring here. All that happens is that you add your new class to the class path and update the application Context!

I will add that this is not the first time we have been bitten by this library. Last February 29 we were hit by this issue.

2 comments:

  1. Formatting is much nicer now. Informative post.

    ReplyDelete
  2. I am using windows Live writer with syntax highlighing plugin.

    ReplyDelete