Link to home
Start Free TrialLog in
Avatar of Inayat081501
Inayat081501

asked on

java ftp program is hangs ...

Hi All,

I am trying to use java to ftp a file from my local pc to an ftp server. Once the connection is established, my program
hangs. Any idea or help will be nice.  Thanks - Inayat.

Here is where it is ... h(b)anging on me ...

C:\Inayat\JavaPractice>java ftp_utility
UserName: bbb\ijilani
LOGIN Successful
RD: \ftptest1
... ... ... ... ... ... ... ....
...(nothing happens)...
... ... ... ... ... ... ... ....

Here is my code....

==============================================

import java.io.*;
import sun.net.ftp.*;

import java.util.*;
import java.net.*;

import java.lang.*;                        

public class ftp_utility2 {

public static void main (String args[]) throws Exception {

String       host = "ftpun01";
int       port = 21;
String       username = "bbb\\ijilani";
String       password = "union28";

String       sourceFile = "HelloCom.java";

String       remoteDirectory = "\\ftptest1";

   put1(host, port, username, password, sourceFile, remoteDirectory);

}

public static void put1(
    String host,                  
    int port,                              
    String username,
    String password,
    String sourceFile,
    String remoteDirectory ) throws Exception
    {

     System.out.println("UserName: " + username);

     // Modify system properties - 03/16/2005
     Properties sysProperties = System.getProperties();
     // Specify proxy settings
     sysProperties.put("proxyHost", "app-proxy");
     sysProperties.put("proxySet",  "true");
     sysProperties.put("proxyPort", "8080");
     System.setProperties(sysProperties);

        FtpClient ftpClient = null;

        try
        {

          ftpClient = new FtpClient(host, port);                  

          ftpClient.login(username, password);
          System.out.println("LOGIN Successful");
          ftpClient.cd(remoteDirectory);
          System.out.println("RD: " + remoteDirectory);

          ftpClient.put(sourceFile);
         }
         finally
         {
          if (ftpClient != null)
          {
            ftpClient.closeServer();
          }
        }
    }
}

==============================================
Avatar of ThummalaRaghuveer
ThummalaRaghuveer

Comment out the line ftpClient.closeServer()  in finally block it works
commenting out ftpClient.closeServer is fine if your application terminates after that (as in your example) but if you keep running after that
then not closing the connection might lead to resource leak.
I would recommend you to use different FTP java library instead of using the undocumented/unsafe sun libraries.
You can look at: http://www.javaworld.com/javaworld/jw-04-2003/jw-0404-ftp_p.html  for a list of libraries.
I personally recommend http://akarta.apache.org/commons/net/  (I use it myself)
Avatar of Inayat081501

ASKER

ThummalaRaghuveer/azarov,

I commented out the line  ftpClient.closeServer()  in the finally block, recompiled and tried. But the file transfer did not take place. Any ideas?

azarov, thanks for your input. But once I have this code working, my objective is to compile it into the oracle database
using its internal Sun JVM and call it using a stored procedure. So I don't know how the other libraries will work.

- Inayat

Because you are running in environment that keeps the JVM alive for a long time then I would not recommend you to not close the connection.
I don't understand why this method hangs (bug?), and I still advice you to use some other library. I think all you need is to add that library to Oracle JVM classpath though I am not sure about it.
ASKER CERTIFIED SOLUTION
Avatar of aozarov
aozarov

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
hi aozarov:

Thank you for your help. I will give you all the points. I am not sure if this site will allow to add another comments once I accept your answer.

Would you mind helping me with fixing the code below? It is doing the opposite - i.e., it does a get function - connects to the ftp server and gets the file and puts it into a folder on the database server. Please excuse my Java knowledge. By the way, I am compiling this code using Oracle's JVM that is integrated into the database.

I get this error when I compile:

JAVA SOURCE SA.my_ftp_get
On line:  0
my_ftp_get:26: Incompatible type for constructor. Can't convert java.lang.String to java.io.OutputStream.

And this is the code,

=========================
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "my_ftp_get" AS
import java.io.*;
import sun.net.ftp.*;
import oracle.sql.*;
public class my_ftp_get {
  public static void get(
    String host,
    NUMBER port,
    String username,
    String password,
    String sourceFile) throws Exception {
    FtpClient ftpClient = null;
    try {
      int lastSlash = sourceFile.lastIndexOf('/');
      String file = sourceFile.substring(lastSlash + 1);
      String directory = sourceFile.substring(0, lastSlash);
    /*// Turn on proxy support when requested.
      if (proxyHost != null && proxyHost.trim().length() > 0 && proxyPort !=null) {
        System.getProperties().put("proxySet", "true");
        System.getProperties().put("proxyHost", proxyHost.trim());
        System.getProperties().put("proxyPort", proxyPort.stringValue());
      }*/
      ftpClient = new FtpClient(host, port.intValue());
      ftpClient.login(username, password);
      ftpClient.cd(directory);
      InputStream is = ftpClient.get(file);
      BufferedOutputStream os = new BufferedOutputStream("F:/clfy/infile/getTest.txt");
      int length;
      while((length = is.read()) != -1) {
        os.write(length);
      }
      is.close();
      os.close();
    } finally {
      if (ftpClient != null) {
        ftpClient.closeServer();
      }
    }
  }
}
/
==================================
You can continue a thread even after giving the points.
Change the code:

BufferedOutputStream os = new BufferedOutputStream("F:/clfy/infile/getTest.txt");
to
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream("F:/clfy/infile/getTest.txt"))

Also do you really mean:
 NUMBER port, ...
or you meant
 int port, ...
If so then also change:
ftpClient = new FtpClient(host, port.intValue());
to
ftpClient = new FtpClient(host, port);
Thank you aozarov,

NUMBER port; is OK coz I am compiling with the JVM inside the oracle database, and I have import oracle.sql.*; at the top of my code. But you are right, if I compile it using JDK, then I have to change it to int port;

I made the first change to the code as you suggested, but I now get this one when I compile:

==============================================
 my_ftp_get:25: Incompatible type for declaration. Can't convert
 sun.net.TelnetInputStream to java.io.BufferedInputStream.

 my_ftp_get:31: Undefined variable or class name: is
 my_ftp_get:34: Undefined variable or class name: is
 Info: 3 errors
==============================================

Here is my code as it stands now,

==============================================
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "my_ftp_get" AS
import java.io.*;
import sun.net.ftp.*;
import oracle.sql.*;
public class my_ftp_get {
  public static void get(
    String host,
    NUMBER port,
    String username,
    String password,
    String sourceFile) throws Exception {
    FtpClient ftpClient = null;
    try {
      int lastSlash = sourceFile.lastIndexOf('/');
      String file = sourceFile.substring(lastSlash + 1);
      String directory = sourceFile.substring(0, lastSlash);
    /*// Turn on proxy support when requested.
      if (proxyHost != null && proxyHost.trim().length() > 0 && proxyPort !=null) {
        System.getProperties().put("proxySet", "true");
        System.getProperties().put("proxyHost", proxyHost.trim());
        System.getProperties().put("proxyPort", proxyPort.stringValue());
      }*/
      ftpClient = new FtpClient(host, port.intValue());
      ftpClient.login(username, password);
      ftpClient.cd(directory);
      BufferedInputStream in = ftpClient.get(file);
      /*BufferedOutputStream os = new BufferedOutputStream("F:/clfy/infile/getTest.txt");*/

 BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream("F:/clfy/infile/getTest.txt"));

      int length;
      while((length = is.read()) != -1) {
        os.write(length);
      }
      is.close();
      os.close();
    } finally {
      if (ftpClient != null) {
        ftpClient.closeServer();
      }
    }
  }
}
/
==============================================
change:
BufferedInputStream in = ftpClient.get(file);

to:
InputStream in

Any reason you want to wrap it in bufferdInputStream?
I don't think there is a reason, but if I am wrong then you can do (instead of the above suggestion):
BufferedInputStream in = new BufferedInputStream(ftpClient.get(file));
Hi aozarov:

I got it. It worked. I don't have any real reason for wrapping it in Buffered class. I first wanted to fix the error and then go back and do some reading.

One last question, when do I use BufferedInputStream and when do I use InputStream? I know I will have to tutor myself on the basics of Java programming. But I just want a brief answer for now.

Thanks for your help - Inayat

BufferedInputStream will do more efficient reading from the source by applying buffering.
What that means is that when you call in.read() which basically "reads" only one byte the BufferedInputStream will actually read more (in one chunk) and will cache
the rest for your subsequent read calls.
That is the preferred way in most of the cases as long as you understand the underlining source (File, Socket, ...).
In this case you get TelnetInputStream (which you don't know much about -> undocumented class) that class might already buffer input (so you do double work), but
also the implication of wrapping it with BufferedInputStream is unknown. This is why I prefer not to wrap it, though it is probably going to be ok.
aozarov:

But in my program I have this:

 InputStream is = ftpClient.get(file);
 BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream("F:/clfy/infile/getTest2.txt"));

As you see, the input is not buffered, but the output is. Will this be a real inconsistency or will it cause any problem under certain conditions?

Thanks - Inayat
>> BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream("F:/clfy/infile/getTest2.txt"));
This goes to a local file (different destination)

>> InputStream is = ftpClient.get(file);
This gets it as TelnetInputStream

Those are two different type of sinks.
I don't think it is inconsistent, but as I said you can always try:
BufferedInputStream is = new BufferedInputStream(ftpClient.get(file)); // which is a bit different from what you did back there.
Personaly, I would not do it.
Thank you, aozarov. :)
:-)