title: How to solve exception with "org.apache.commons.net.ftp.FTPClient"
body: <p><p>Im not sure if this is a similar problem as I faced since it doesn't state an Exception:
  <a href="https://stackoverflow.com/questions/2576647/issue-with-org-apache-commons-net-ftp-ftpclient-listfiles">Issue with org.apache.commons.net.ftp.FTPClient listFiles()</a></p>
  
  <p>I'm trying to use this <code>class FTPUtil</code> to download the root folder:
  <a href="https://www.codejava.net/java-se/ftp/how-to-download-a-complete-folder-from-a-ftp-server" rel="nofollow noreferrer">https://www.codejava.net/java-se/ftp/how-to-download-a-complete-folder-from-a-ftp-server</a></p>
  
  <p>at the line 
       <code>FTPFile[] subFiles = ftpClient.listFiles(dirToList);</code>
  I get this Exception:</p>
  
  <pre><code> java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.net.InetAddress.getHostAddress()' on a null object reference
      at org.apache.commons.net.ftp.FTPClient._openDataConnection_(FTPClient.java:938)
      at org.apache.commons.net.ftp.FTPClient._openDataConnection_(FTPClient.java:785)
      at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:3409)
      at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:3339)
      at org.apache.commons.net.ftp.FTPClient.listFiles(FTPClient.java:3016)
      at com.censored.FTPUtil.downloadDirectory(FTPUtil.java:39)
  </code></pre>
  
  <p>I don't really understand which Object is null and why.
  As <code>String parentDir</code> I tried <code>""</code> and <code>"\"</code> both with the same result I don't think the input is wrong.<br/>
  The FTP server is running fine I see that my program logs in successful and file zilla can also access the folder.</p>
  
  <p>EDIT:</p>
  
  <p>Here is the class from the link I'm using:</p>
  
  <pre><code>package com.censored;
  
  import java.io.BufferedOutputStream;
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.OutputStream;
  
  import org.apache.commons.net.ftp.FTP;
  import org.apache.commons.net.ftp.FTPClient;
  import org.apache.commons.net.ftp.FTPFile;
  
  /**
   * This utility class implements a method that downloads a directory completely
   * from a FTP server, using Apache Commons Net API.
   *
   * @author www.codejava.net
   *
   */
  public class FTPUtil {
  
      /**
       * Download a whole directory from a FTP server.
       * @param ftpClient an instance of org.apache.commons.net.ftp.FTPClient class.
       * @param parentDir Path of the parent directory of the current directory being
       * downloaded.
       * @param currentDir Path of the current directory being downloaded.
       * @param saveDir path of directory where the whole remote directory will be
       * downloaded and saved.
       * @throws IOException if any network or IO error occurred.
       */
      public static void downloadDirectory(FTPClient ftpClient, String parentDir,
              String currentDir, String saveDir) throws IOException {
          String dirToList = parentDir;
          if (!currentDir.equals("")) {
              dirToList += "/" + currentDir;
          }
  
          FTPFile[] subFiles = ftpClient.listFiles(dirToList); //This line gives the Exception
  
          if (subFiles != null &amp;&amp; subFiles.length &gt; 0) {
              for (FTPFile aFile : subFiles) {
                  String currentFileName = aFile.getName();
                  if (currentFileName.equals(".") || currentFileName.equals("..")) {
                      // skip parent directory and the directory itself
                      continue;
                  }
                  String filePath = parentDir + "/" + currentDir + "/"
                          + currentFileName;
                  if (currentDir.equals("")) {
                      filePath = parentDir + "/" + currentFileName;
                  }
  
                  String newDirPath = saveDir + parentDir + File.separator
                          + currentDir + File.separator + currentFileName;
                  if (currentDir.equals("")) {
                      newDirPath = saveDir + parentDir + File.separator
                                + currentFileName;
                  }
  
                  if (aFile.isDirectory()) {
                      // create the directory in saveDir
                      File newDir = new File(newDirPath);
                      boolean created = newDir.mkdirs();
                      if (created) {
                          System.out.println("CREATED the directory: " + newDirPath);
                      } else {
                          System.out.println("COULD NOT create the directory: " + newDirPath);
                      }
  
                      // download the sub directory
                      downloadDirectory(ftpClient, dirToList, currentFileName,
                              saveDir);
                  } else {
                      // download the file
                      boolean success = downloadSingleFile(ftpClient, filePath,
                              newDirPath);
                      if (success) {
                          System.out.println("DOWNLOADED the file: " + filePath);
                      } else {
                          System.out.println("COULD NOT download the file: "
                                  + filePath);
                      }
                  }
              }
          }
      }
  
      /**
       * Download a single file from the FTP server
       * @param ftpClient an instance of org.apache.commons.net.ftp.FTPClient class.
       * @param remoteFilePath path of the file on the server
       * @param savePath path of directory where the file will be stored
       * @return true if the file was downloaded successfully, false otherwise
       * @throws IOException if any network or IO error occurred.
       */
      public static boolean downloadSingleFile(FTPClient ftpClient,
              String remoteFilePath, String savePath) throws IOException {
          File downloadFile = new File(savePath);
  
          File parentDir = downloadFile.getParentFile();
          if (!parentDir.exists()) {
              parentDir.mkdir();
          }
  
          OutputStream outputStream = new BufferedOutputStream(
                  new FileOutputStream(downloadFile));
          try {
              ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
              return ftpClient.retrieveFile(remoteFilePath, outputStream);
          } catch (IOException ex) {
              throw ex;
          } finally {
              if (outputStream != null) {
                  outputStream.close();
              }
          }
      }
  }
  </code></pre>
  
  <p>And this my code calling it (censored the unrelevant stuff I dont have the permission to show the full class):</p>
  
  <pre><code>val server = "10.0.2.2"  // Because of Emulator
  val port = 8080 //yeah I know not standard port, this will change
  val user = "censored"
  val pass = "censored"        
  
  val remoteDirPath = ""   //also tried "/"
  val saveDirPath = File(myFilesDir, "fromFTP/").absolutePath   //ignore myFilesDir the Debuger shows that its set correct and it isnt relevant before the Exception
  
  val ftpClient = FTPClient()
  
  
  
      try {
          // connect and login to the server
          ftpClient.connect(server, port)
          ftpClient.login(user, pass)
  
          // use local passive mode to pass firewall
          ftpClient.enterLocalPassiveMode()
  
          println("Connected")
  
          FTPUtil.downloadDirectory(ftpClient, remoteDirPath, "", saveDirPath) //this line is the one giving the exception
  
          // log out and disconnect from the server
          ftpClient.logout()
          ftpClient.disconnect()
  
          println("Disconnected")
      } catch (ex: IOException) {
          ex.printStackTrace()
      }
  </code></pre>
  
  <p><strong>Update:</strong>
  During Debuging I found that this <code>if</code> in class <code>FTPClient extends FTP</code> is true:</p>
  
  <pre><code> if (__remoteVerificationEnabled &amp;&amp; !verifyRemote(socket))
          {
              socket.close();
  
              throw new IOException(
                      "Host attempting data connection " + socket.getInetAddress().getHostAddress() +
                      " is not same as server " + getRemoteAddress().getHostAddress());
          }
  
          return socket;
  </code></pre>
  
  <p>I think <code>socket.getInetAddress()</code> causes an exception (inside of the outer exception) because the Socket is already closed? This would mean that the <code>FTPClient</code> itself contains a bug? However I think the solution for my problem is that the <code>if (__remoteVerificationEnabled &amp;&amp; !verifyRemote(socket))</code> is true, so somehow this if must become false. Why is it true? What kind of verification is this?</p>