Downloading an XML file via FTP - java

I have a list of feeds in a database that I use to download a XML file from a FTP server and then parse it. The scrpt is bundled up into a jar file which is run daily using Windows Task Scheduler. Occasionally the request get haulted at grabbing a certain xml file. So far it has happened about 3 times in 2 weeks with no real pattern that I can see.
When it does mess up, I go to the computer it is being run from, I see the command window open and it is stopped before the xml has been fully downloaded. If I close the command window and run the task manually everything will work fine.
The code that I am using to download the xml file is:
private void loadFTPFile(String host, String username, String password, String filename, String localFilename){
System.out.println(localFilename);
FTPClient client = new FTPClient();
FileOutputStream fos = null;
try {
client.connect(host);
client.login(username, password);
String localFilenameOutput = createFile(assetsPath + localFilename);
fos = new FileOutputStream(localFilenameOutput);
client.retrieveFile(filename, fos);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null)
fos.close();
client.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This function is being called in a loop and when it fails, everything stops and the script doesn't go onto the next feed.
I'm not sure what is happening, possibly the connection being lost, but I would think that the try/catch would catch if that is happening. I'm not sure if a timeout would do the trick or threads need to be used (but I've never worked with threads)
Could anyone point me in the right direction onto why this is happening and what I can do to fix the problem

UPDATE - Set a timeout for the data connection
Since the last file is only partially downloaded, and given the source of FTPClient.retrieveFile(), I think it may be a problem on the server side (something that make it hang, or even die - who knows). Obviously one can't repair the server or even know what's going on there, anyway I suggest to add a timeout with setDataTimeout(int) and catch the possible SocketTimeoutException separately to be logged in a different place and maybe sent to the FTP server admins (along with the time information when it happened) so they can merge the logs and see what's the issue.
OLD ANSWER
I didn't notice that you connect and login for each and every file, so the following is just an optimization not to close the control connection and succesfully logout, but it should not address the problem.
You could start the JVM in debug mode and attach a debugger when it hangs, anyway according to this answer and this thread it can be a timeout problem on the network equipment devices (routers). From the FTPClient Javadoc
During file transfers, the data connection is busy, but the control
connection is idle. FTP servers know that the control connection is in
use, so won't close it through lack of activity, but it's a lot harder
for network routers to know that the control and data connections are
associated with each other. Some routers may treat the control
connection as idle, and disconnect it if the transfer over the data
connection takes longer than the allowable idle time for the router.
One solution to this is to send a safe command (i.e. NOOP) over the control connection to reset the router's idle timer. This is enabled as follows:
ftpClient.setControlKeepAliveTimeout(300); // set timeout to 5 minutes

Do you check the return status of any of the calls or is that the code?
There is a call completePendingCommand() that has to be used on occassion. That may be something to look into.
Also, you won't see an IO exception, I belive it gets repackaged as a CopyStreamException
You might want to also change the return value to a boolean since you trap the exceptions, at least the calling loop will know whether the tranfer happened or not.
private boolean loadFTPFile(String host, String username, String password, String filename, String localFilename){
System.out.println(localFilename);
FTPClient client = new FTPClient();
FileOutputStream fos = null;
try {
client.connect(host);
int reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)){
client.disconnect();
System.err.println("FTP server refused connection.");
return false;
}
if (!client.login(username, password)){
client.logout();
return false;
}
String localFilenameOutput = createFile(assetsPath + localFilename);
fos = new FileOutputStream(localFilenameOutput);
boolean result = client.retrieveFile(filename, fos);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
if (result){
System.out.println("\tFile Transfer Completed Successfully at: " + sdf.format(Calendar.getInstance().getTime()));
// ftp.completePendingCommand();
}
else {
System.out.println("\tFile Transfer Failed at: " + sdf.format(Calendar.getInstance().getTime()));
}
return result;
}catch (CopyStreamException cse){
System.err.println("\n\tFile Transfer Failed at: " + sdf.format(Calendar.getInstance().getTime()));
System.err.println("Error Occurred Retrieving File from Remote System, aborting...\n");
cse.printStackTrace(System.err);
System.err.println("\n\nIOException Stack Trace that Caused the Error:\n");
cse.getIOException().printStackTrace(System.err);
return false;
}catch (Exception e){
System.err.println("\tFile Transfer Failed at: " + sdf.format(Calendar.getInstance().getTime()));
System.out.println("Error Occurred Retrieving File from Remote System, aborting...");
e.printStackTrace(System.err);
return false;
} finally {
try {
if (fos != null)
fos.close();
client.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}

It's not a threading issue. Chances are it is caused by something in the loop since that code looks like it should clean up just fine. That said, for testing you will probably want to add
catch (Exception e) {
e.printStackTrace();
}
after the IOException catch clause. It's possible that another exception is being thrown.
Another thing, if you are pulling results from the database result set one at a time and doing the FTP gets, that might be a problem. Unless the results are all brought back by the JDBC call at once, that too could time out. Not all database queries actually return the entire result set to the client at once.

Related

Start and Stop Tomcat from java code

Based in a code I saw in Stackoverflow and other pages on Internet, I've created a method to stop and start tomcat at the moment I'll run a process in my system because I need to clean memory in my OS, I use System.gc() but still not enough to free memory, this is the code:
Global declaration:
private String server = "localhost";
Method to stop-start tomcat:
public void tomcat(){
try{
Socket s = new Socket(server,8005);
if(s.isConnected()){
PrintWriter print = new PrintWriter(s.getOutputStream(),true);
print.println("SHUTDOWN"); /*Command to stop tomcat according to the line "<Server port="8005" shutdown="SHUTDOWN">" in catalina_home/conf/server.xml*/
print.close();
s.close();
}
Runtime.getRuntime().exec(System.getProperty("catalina.home")+"\\bin\\startup.bat"); /*Instruction to run tomcat after it gets stopped*/
}catch (Exception ex){
ex.printStackTrace();
}
}
The code line to start tomcat works perfectly, but no the instructions to stop it because, when I instance the socket, gives me the following message: Connection refused: connect.
How can I solve this? or, is there another way to stop tomcat?
Thanks in advance.
public static void shut_server(String lien)
{
try {
Process child = Runtime.getRuntime().exec(lien+"/shutdown.sh");
System.out.println("Serveur est atteins");
} catch (IOException ex) {
Logger.getLogger(Installation.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("erreur de demarrage");
}
}
lien = path to your tomcat bin file
for example - /home/zakaria/Téléchargements/apache-tomcat-8.0.21/bin
I had similar issue. I was getting the "Connection refused: connect" error message on creating the socket.
However, my use case is different from the one posted by Vlad. When the Tomcat server is starting up, my app is checking availability of some resources and if they are not, it needs to shutdown the server.
I added a 30 seconds sleep just before the line creating socket:
try {
Thread.sleep(30000);
}
catch (Exception excp) {}
Socket socket = new Socket("localhost", port);
and it started working.
I think when Tomcat is starting up it needs some time to make the shutdown port ready to work.
The selection of 30 seconds is arbitrary, it could be probably shorter.
FYI, my Tomcat is running as Windows service.

FTP server dies while ftp4j client downloads a file

I use sauronsoftware.ftp4j.FTPClient to do scheduled file downloads from FTP servers.
My problem is that FTP server suddenly dies while the client downloads a file from it.
This is what i do:
for (FTPFile remoteFile : remoteFiles) {
String remoteFileName = remoteFile.getName();
String localPath = ftpDir.getLocalPath() + remoteFileName;
log.debug("Downloading remote file {} to local path {}", remoteFileName, localPath);
try {
client.download(remoteFileName, new File(localPath));
if (!ftpDir.isLeaveFilesOnServer()) {
//Delete remote file
client.deleteFile(remoteFileName);
}
} catch (IllegalStateException e) {
log.error("FTPException ",e);
fcr.addErrorFile(remoteFileName);
} catch (IOException e) {
log.error("FTPException ",e);
The problem is that download(...) runs by separate thread and when FTP server dies this thread continues to run anyway like forever. Is there a way to come around this problem or should i use another FTP client that can handle cases like this?
I'm not sure if your problem is your FTP connection dies sudden and unexpedtecly, or if the problem is the main thread finished its execution before files are downloaded. If we are talking about the second scenario, then maybe you can use this other method of the same FTPClient class:
public void download(java.lang.String remoteFileName,
java.io.File localFile,
FTPDataTransferListener listener)
and then make the main thread to wait until all downloads have finished before ending

Interrupting Java DataInputStream readFully()

I have a Java applet that streams video (MJPEG) from a server. I wrote a proxy server in C# (Windows service) to put between the applet and multiple video servers. A HTML/CSS/Js frontend is used along with the Java applet. All functionality works fine (finally!!!), except one thing.
The video server allows you to play back recorded video through a REST interface. When the clip is done, the server leaves the connection open in case you want to send it commands like rewind or seek. The clip is being played fine in the applet until the end. If you try to start a new clip (which entails sending a command from Javscript to the applet), the browser freezes up. However, subsequent commands that would use the same connection work, such as play, pause, and seek. If I stop the windows service, the browser becomes responsive again.
This is what I'm assuming is happening: The clip ends (or is paused); no more data is sent but the connection is still active. The applet is waiting on the proxy for the next frame, but the proxy is waiting on the video server for the next frame, which is not going to send any more data.
This is the code in a while loop that reads each frame
byte[] img = new byte[mContentLength];
inputStream.skipBytes(headerLen);
inputStream.readFully(img);
I need to interrupt this code somehow.
When a new video clip is selected in the HTML frontend, we notify the applet, which calls disconnect() on the CameraStream class. This is that function:
// DataInputStream inputStream
// HttpURLConnection conn
public void disconnect() {
System.out.println("disconnect called.");
if(running) {
running = false;
try {
// close the socket
if(inputStream != null) {
inputStream.close();
}
if(conn != null) {
conn.disconnect();
}
inputStream = null;
System.out.println("closed.");
} catch(Exception ignored) {
System.out.println("exc:" + ignored.getMessage());
main.reportErrorFromThrowable(ignored);
}
}
}
To test this, I let a quick clip play and run to the end. I then select a new clip. In my Java console, I get the output disconnect called. but I don't get the subsequent closed. message, nor does that generic Exception get caught. When I stop the Windows service, I finally get the closed. message, so it seems like inputStream.close(); is blocking.
So I guess my question is how can I stop the blocking? Is the readFully(img) call blocking? Or is it the disconnect function (as suggested by the console output I get)?
edit: just to clarify, I wrote the Java applet, HTML, CSS, Javascript, and C# proxy server, so I have access to all of that code. The only code I can't modify is that of the REST interface on the video server.
edit2: i meant to make bounty for this post https://stackoverflow.com/questions/12219758/proxy-design-pattern
In general, Java I/O methods block. The best solution appears to be to create another thread for reading the data and using NIO buffers. Example of NIO-based read (warning: untested!):
// get the InputStream from somewhere (a queue possibly)
ReadableByteChannel inChannel = Channels.newChannel(inputStream);
ByteBuffer buf = ByteBuffer.allocate(mContentLength + headerLen);
inChannel.read(buf);
byte[] img = new byte[mContentLength];
inChannel.get(img, headerLen, mContentLength);
This code creates a Channel from the InputStream and uses the Channel to read data. The JavaDoc for the ReadableByteChannel.read(ByteBuffer) function says that interrupting the thread that contains the call to inChannel.read(buf) will stop the read.
You will have to adapt this code, I just pulled it out of my head. Good luck!
I finally figured out the answer:
public void disconnect() {
if(running) {
running = false;
try {
try{
// had to add this
conn.getOutputStream().close();
}
catch(Exception exc){
}
// close the socket
if(inputStream != null) {
inputStream.close();
}
if(conn != null) {
conn.disconnect();
}
inputStream = null;
} catch(Exception ignored) {
main.reportErrorFromThrowable(ignored);
}
}
}
Even though I'm using an HttpUrlConnection, which is one way and doesn't have an output stream, trying to close the output stream raised an exception and for some reason made it all work.

Java app throws ClosedByInterruptException immediately when opening a socket, cause?

I have a java app that holds open many connections to an address, probably in the ballpark of 2,000 at once, with hardly any activity, mostly open for monitoring purposes passing a few bytes every now and then. When new connections need to be opened up, it automatically opens them and adds them to its pool. Sometimes though, for an unknown reason, the application receives a ClosedByInterruptException immediately during/after creating the socket to the remote address. To the best of my knowledge, this only occurs on the client side as a result of an interrupt signal to the thread. I have checked and rechecked the source code surrounding the problem area and it seems ok. I was hoping I could get someone's expertise as to if there could be an alternate cause, besides source code, for instance, is there a system reason that causes this? Is there a hardware cause? Server level/router level? My network knowledge I would consider amateur, but is 2K connections too many for a router, or no?
INFO [08 Sep 2011 23:11:45,982]: Reconnecting id 20831
ERROR [08 Sep 2011 23:11:45,990]: IOException while creating plain socket channel
java.nio.channels.ClosedByInterruptException
at java.nio.channels.spi.AbstractInterruptibleChannel.end(AbstractInterruptibleChannel.java:184)
at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:518)
at com.*.createSocketChannelPlain(MyTask.java:441)
at com.*._executeTask(MyTask.java:176)
at com.*.executeTask(MyTask.java:90)
at com.*.ThreadPool$WorkerThread.run(ThreadPool.java:55)
ERROR [08 Sep 2011 23:11:45,990]: Could not open socket
WARN [08 Sep 2011 23:11:45,990]: WorkerThread_24 received interrupted exception in ThreadPool
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at com.*.TaskQueue.getTask(TaskQueue.java:39)
at com.*.ThreadPool$WorkerThread.run(ThreadPool.java:48)
Update: I would like to try and offer all I can to help others contribute to a diagnosis. So here is the actual function where the exception occurs, only difference being the line marking I added to line 441.
private SocketChannel createSocketChannelPlain() throws TaskFailedException {
SocketChannel socketChannel = null;
try {
// Create a non-blocking socket channel to use to communicate for imap connection
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
try {socketChannel.socket().setSoLinger(true, 0);} catch (Exception e) {}
try {socketChannel.socket().setKeepAlive(true);} catch (Exception e) {}
/*Line 441*/ socketChannel.connect(new InetSocketAddress(_HOSTNAME, _PORT));
//System.out.println("Started connection");
// Complete connection
while (!socketChannel.finishConnect()) {
// do something until connect completed
try {
//do what you want to do before sleeping
Thread.sleep(500);//sleep for 500 ms
//do what you want to do after sleeping
} catch(InterruptedException ie){
//If this thread was interrupted by another thread
try { socketChannel.close(); } catch (Exception e) {}
finally { socketChannel = null; }
break;
}
}
//System.out.println("Finished connecting");
return socketChannel;
} catch (IOException e) {
logger.error("IOException while creating plain socket channel to gmail", e);
try { socketChannel.close(); } catch (Exception e1) {}
finally { socketChannel = null; }
//throw new TaskFailedException("IOException occurred in createSocketChannel");
}
return socketChannel;
}
What OS are you running this on? I don't know about Windows, but on Linux (and presumably other Unix-like OSes), you can run out of file handles by having large numbers of sockets. You can work around this by doing ulimit -n 8192 or similar before running the Java app. Alternatively, edit /etc/security/limits.conf and set nofile. All of that said, ClosedByInterruptedException would be an odd way to notice this.
If the above isn't the issue, the next thing I'd try would be to run tcpdump (if we're talking about a GUI-less machine) or Wireshark (if we aren't) and capture the traffic your program's generating, looking for weird things happening at the time that connection starts.

apr_socket_recv: An established connection was aborted by the software in your host machine

I'm creating a small server using java.nio, but when trying to stress test it I keep getting messages about the connection being reset on the server side, or more specifically:
apr_socket_recv: An established connection was aborted by the software in your host machine
I've tried to narrow it down to the most simple of loops, but still no luck. I can get the error after a hundred or so connections, or maybe just after 1 or 2.
Here's the server loop:
byte[] response = ("HTTP/1.1 200 OK\r\n"
+ "Server: TestServer\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n"
+ "<html><b>Hello</b></html>").getBytes();
SocketChannel newChannel = null;
while (active) {
try {
//get a new connection and delegate it.
System.out.print("Waiting for connection..");
newChannel = serverSocketChannel.accept();
System.out.println("ok");
newChannel.configureBlocking(true);
newChannel.write(ByteBuffer.wrap(response));
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
newChannel.close();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I've tried checking if the write didn't write all requested byte, but it seemingly does. Interestingly enough, calling System.gc() after each newChannel.close() makes the problem disappear (but in return, it's horribly slow). So either I'm not releasing all resources I should release, or the application just needs a pause..
I'm losing all of my best years on this. Oh, and by the way.. if I ignore writing to the channel and just close after I accept the connection, the problem still doesn't go away.
Well I found it out, so I might as well share it.
My app needed a pause. It was simply going too fast, and closing the connection before the client had written all of its request data. The fix would be to keep on reading until the entire HTTP request had been received. D'oh.. lesson learned.
From the docs for SocketChannel#Write (emphasis mine):
An attempt is made to write up to r bytes to the channel, where r is
the number of bytes remaining in the buffer, that is, src.remaining(),
at the moment this method is invoked.
[...]
Returns: The number of bytes written, possibly zero.
It's up to you to check the return value from the write call (which you're not doing presently), and issue successive write calls until the whole of the buffer has been sent. Something like this, I guess:
ByteBuffer toWrite = ByteBuffer.wrap(response);
while (toWrite.remaining() > 0) {
newChannel.write(toWrite);
}
You'll obviously get aborts if you don't write all of your response data and then just close the socket.

Categories

Resources