0

I am writing a web app that I want to use to perform FTP tasks (downloads)

I have Apache FTPS server installed in Tomcat and a Java Client ready to initiate the transfers.

The client will be invoked by the Servlet.

For example:

http://laptop:8080/MyServlet?action=download&from=desktop&file=C:/home/fred/file.xml 

Would tell the instance on my laptop to download file.xml from my desktop.

EDIT: Apologies, I never made this very clear.

There will be an FTP server at both ends of this process. 1 on my remote laptop and 1 on my local desktop. So in a nutshell I am submitting an FTP 'get' request to the Servlet on the remote side. The Servlet then kicks off an FTP process to pull the file across.

My Servlet is all set to receive the GET parameters and do the work.

If the file is quite big then each request will take a long time to complete. I want the Servlet resources freed up as quickly as possible.

Ideally I'd like the following things to happen:

  1. User to send URL to Servlet
  2. Servlet to digest the URL and work out what file and where from etc...
  3. Servlet to pass info to a Thread
  4. Servlet to come back with an "In progress" message
  5. Request completes
  6. Thread is still working in the background downloading the file

At this time I'm not too concerned with the Servlet having knowledge of the success of the thread, I just need it to kick one off and forget about it. The FTP process will have separate logging elsewhere for any issues.

I am interested in the concept of creating a Threadpool in the WebApp and fetching a thread from there but again, all examples I've found are old and don't really cater for my level of understanding.

There are a few similar questions on StackOverflow with this being the most similar to what I am asking for but it just hints at something ExecutorService that I have no prior knowledge of. How would I set this up in a WebApp ? What is recommended way for spawning threads from a servlet in Tomcat

For info, I have researched this and have found a lot of incomplete examples that require a better understanding than I currently have, or hints towards what is required. Also a lot of the examples I've read are a few years old, nothing recent. I'm hoping there might be a magical one-liner to do everything I need (doubtful) that has come about in the last year or so :) I'm new to Threading concepts in Java, I understand Threading in general so appreciate any help you can offer me.

Trevor

Community
  • 1
  • 1
thonnor
  • 1,206
  • 2
  • 14
  • 28
  • Do you want to use HTTP protocol (what you are describing) or FTP protocol (different protocol and different port) as said in the title ? – Serge Ballesta Sep 19 '14 at 12:17
  • Hello Serge, I want to use HTTP for the request to the Servlet on port 8080 which then triggers off an FTP process that downloads the file on port 21. – thonnor Sep 19 '14 at 12:49

1 Answers1

0

I'm not sure I have really understood what you want ...

client                                      server
send request (via HTTP) and wait for
         HTTP response
                                            analyse request and find file to send
                                            ... (processing)
                                            send HTTP response (1) with ?
opens FTP connection (could not open it before)
                                            receive FTP request (command connection)
                                            send file (data connection)
file is received and saved locally

If the client side is a browser, it should be enough for the response (1) to be a redirect to an URL like ftp://host/path/to/file, because all major browsers know of the FTP protocal and are able to use it to download a file.

The problem is not on server side, you can easily spawn a thread that could acts as a FTP client or (probably harder) as a FTP server, but I cannot imagine better than a redirection on client side : the client has open a HTTP connection than cannot be used for a FTP transfert and it must open a new connection for the FTP request. As it is a new connection, how do you want it to be processed by the thread launched at previous step ? There is no notion of session in FTP and there's no easy way to identify the right request.

Edit per comment:

Ok, I appears that you just want to do defered processing on server after request completion. You have two ways of doing that :

  • as suggested by you tags, use a worker thread to do the job. Your servlet is plain Java and you can create a thread like you would do in any other Java application. If you are interested in getting later the result of the defered processing, you could give a reference the the session (or simply to a session attribute) to the thread where it will be able to put its advancement and/or completion status. This requires some more boiler plate code but is guaranteed to work (examples below)
  • you can close the HTTP connection before the servlet returns. It is not explicitely guaranteed per the official servlet specs, but I found it to work at least in tomcat 7. You will find more details on that on this other post Servlet - close connection but not method

Example using simple threads, and storing status in session :

public class ThreadedServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest hsr, HttpServletResponse hsr1) throws ServletException, IOException {
        String fileName = null;
        // preliminary work ...
        Worker worker = new Worker(fileName);
        final HttpSession session = hsr.getSession();
        synchronized (session) {
            List<Status> statuses = (List<Status>) session.getAttribute("statuses");
            if (statuses == null) {
                statuses = new ArrayList<Status>();
            }
            statuses.add(new Status(fileName));
        }
        Thread thr = new Thread(worker);
        thr.start();
        // write the response either directly or by forwarding to a JSP
    }

    public static class Status implements Serializable {
        private String fileName;
        private WStatus status;

        public Status(String fileName) {
            this.fileName = fileName;
        }

        public String getFileName() {
            return fileName;
        }

        public void setFileName(String fileName) {
            this.fileName = fileName;
        }

        public WStatus getStatus() {
            return status;
        }

        public void setStatus(WStatus status) {
            this.status = status;
        }
    }

    public enum WStatus {
        STARTED,
        RUNNING,
        COMPLETED
    }

    private static class Worker implements Runnable {

        private String fileName;
        private Status status;

        public Worker(String fileName) {
            this.fileName = fileName;
        }

        @Override
        public void run() {
            status.setStatus(WStatus.RUNNING);
            // do your stuff ...
            status.setStatus(WStatus.COMPLETED);
        }
    }
}
Community
  • 1
  • 1
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • Think of it in its basic elements (forgetting FTP tasks for a moment) On a Local client using a browser... I want to connect to a remote Servlet. I want that Servlet to spawn a thread on the remote machine to do some work. Whilst that work is in progress I want the Servlet to report back with 200 (or whatever number) and that is its job completed The Servlet could do the work but I want it passed onto a worker thread instead so that the application doesn't hang. – thonnor Sep 19 '14 at 13:27
  • I've made an edit to the main question now to explain that there will be an FTP process running on both ends (client & server). The servlet is being asked to download/get the file from my local client. There is no pushing of files in this application. Apologies. – thonnor Sep 19 '14 at 13:37