Finishing a HttpServletResponse but continue processing

12,381

Solution 1

Here's how I've handled this situation:

  1. When the app starts up, create an ExecutorService with Executors.newFixedThreadPool(numThreads) (there are other types of executors, but I suggest starting with this one)
  2. In doPost(), create an instance of Runnable which will perform the desired processing - your task - and submit it to the ExecutorService like so: executor.execute(task)
  3. Finally, you should return the HTTP Status 202 Accepted, and, if possible, a Location header indicating where a client will be able to check up on the status of the processing.

I highly recommend you read Java Concurrency in Practice, it's a fantastic and very practical book.

Solution 2

You can continue processing in a separate Thread.

The response is commited once you return from doPost() method.

Solution 3

On possibility for your servlet to accept a request for processing in the background, is for the servlet to hand off processing to a separate thread which then executes in the background.

Using Spring, you can invoke a separate Thread using the a TaskExecutor. The advantage of using spring over standard JDK 5 java.util.concurrent.Executor is that if you're on application servers that need to use managed threads (IBM websphere or Oracle weblogic), you can use the WorkManagerTaskExecutor to hook into the CommonJ work managers.

Another alternative would be to move the long query logic into a Message Driven Bean or Message Driven POJO (Spring JMS can help here) and let the servlet simply post a message on a JMS queue. That would have the advantage that should the load on your web container become too great because of your long running query, you could easily move the MDB onto a different (dedicated) system.

Share:
12,381

Related videos on Youtube

Stevko
Author by

Stevko

Full-stack mobile software architect consulting for start-up and enterprise companies. Innovative builder of secure, enterprise-class, business-critical systems. Proven track record of launching new revenue opportunities. Repeat clients in healthcare, university, and commerce space. Expertise in bootstrapping and mentoring teams with agile, web, and cloud technologies. Translation of business objectives into Agile projects that build cloud-based applications. Technical Expertise Client: PhoneGap, Cordova, HTML5, JavaScript, CSS, JSON, Sencha ExtJS, Google Web Toolkit, Sencha GXT, AJAX, WebSockets, Web Workers Cloud: Google App Engine, Amazon Web Services Servers: Expert Java, J2EE application servers, SOAP/REST web services, JMS, NoSQL, MySQL, bash Tools: Open source, Third party APIs, Atlassian Jira, Git, BitBucket, Slack, svn Information security, network architecture, micro-controllers, natural language processing, machine learning “If everything seems under control, you're just not going fast enough.”Mario Andretti "We are like tenant farmers chopping down the fence around our house for fuel when we should be using Natures inexhaustible sources of energy — sun, wind and tide. ... I'd put my money on the sun and solar energy. What a source of power! I hope we don't have to wait until oil and coal run out before we tackle that." Thomas Edison (1931)

Updated on April 16, 2022

Comments

  • Stevko
    Stevko about 2 years

    I have a situation that seems to fit the Async Servlet 3.0 / Comet situation but all I need to do is return a 200 response code (or other) after accepting the incoming parameters.

    Is there a way for a HttpServlet to complete the http request/response handshake and yet continue processing?

    Something like...

    doPost( req, response ) {
       // verify input params...
       response.setStatus( SC_OK );
       response.close();
       // execute long query
    }     
    

    EDIT: Looking at the javax.servlet package - the proper phrasing to my question is

    How do I commit a response?

    as in Servlet.isCommitted()

  • Stevko
    Stevko about 14 years
    I'm running into the URL Fetch service 5 sec timeout on perfectly good requests originating from a Google app engine. There is no need for the App Engine Requestor to block waiting for OK response from something that may take a very long time to complete processing.
  • Stevko
    Stevko about 14 years
    While I agree with all the responses, this one has the least amount of complexity involved. Thanks to pajton, beny23 and avi for your input.
  • Politank-Z
    Politank-Z about 9 years
    Could you expand on this?
  • Tintin
    Tintin about 7 years
    how do I do this, if I want to use executor.submit() instead of .execute? I want to use .submit so that I can get hold of "futures" and know when all the tasks have completed (based on which I have to do certain processing?).
  • Nicolás Marzano
    Nicolás Marzano about 6 years
    It's better not to instantiate an ExecutorService every time the servlet gets a request or else you'll start creating a lot of threads that never die, at least per the newSingleThreadExecutor() documentation.