kkudi
kkudi

Reputation: 1667

tomcat - start thread in servlet and send response

How can I start a thread which will run in the background but the response will be sent to the user immediately?

I'm trying to upload a file from an android device. While the uploading process works fine, I'd like to tell the user that the process has finished once the file has been uploaded from his end.

I have checked that the call to ServletFileUpload.parseRequest() is what takes a long time.

        ServletFileUpload uploadHandler = new ServletFileUpload(fileItemFactory);

        List items = uploadHandler.parseRequest(request);

So basically I'm looking for a way where I can tell the user "hey you've done your part", now it's the servlet's turn to do all the processing.

but I can't because parseRequest blocks.

Am I wrong in that it blocks because that's when it's actually being sent by the device?

Uploading on android:

        while (bytesRead > 0)
        {
            task.myPublishProgress(totalBytesRead, fileSize);

            dos.write(buffer, 0, bufferSize);

            bytesAvailable = fileInputStream.available();

            bufferSize = Math.min(bytesAvailable, maxBufferSize);

            bytesRead = fileInputStream.read(buffer, 0, bufferSize);

            totalBytesRead+= bytesRead;

        }

        // send multipart form data necesssary after file data...
        dos.writeBytes(lineEnd);

        dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

        // close streams

        fileInputStream.close();

        dos.flush();

        Log.i(TAG ,"Database file with name " + this.fileName + " has been successfully written");

        InputStream is = conn.getInputStream();

        // retrieve the response from server

        int ch;

        StringBuilder b = new StringBuilder();

        while( ( ch = is.read() ) != -1 ){
            b.append( (char)ch );
        }

        dos.close();

handling on server:

                DiskFileItemFactory  fileItemFactory = new DiskFileItemFactory ();

            ServletFileUpload uploadHandler = new ServletFileUpload(fileItemFactory);
            /*
             * Parse the request
             */
            System.out.println("parsing the request....");
            **List items = uploadHandler.parseRequest(request);**
            FileItem item = (FileItem) items.get(0);
            fileName = item.getName();

            File file = new File(destinationDir, fileName);
            item.write(file);

I'd like the servlet not too block on parseRequest, but instead handle that in a thread perhaps, and send the response to the client.

thanks

Upvotes: 1

Views: 1714

Answers (1)

BalusC
BalusC

Reputation: 1109322

This is not possible in standard HTTP. The response can only be sent when the request body has fully been consumed. As long as you don't call uploadHandler.parseRequest(request);, the files are not been uploaded. You would be lying if you tell "You're done!" prior this point.

Only after calling uploadHandler.parseRequest(request) and having the items, you could tell the user in all honesty that he's done. The remnant can however perfectly be done in a separate thread. I'd suggest to create a fixed threadpool for that which is managed by a ServletContextListener. However, I think this is a bit exaggerated when you aren't doing any expensive tasks with the uploaded files.

As to the concrete problem (that the application seems to do nothing while it is busy to upload the files), I'd rather suggest to solve the problem at the client side. Get the size of the files, get hold of the count of the bytes sent to the outputstream and then show some progress bar in the client side so that the client get informed about the progress.

Upvotes: 2

Related Questions