Implementing long polling in an asynchronous fashion
Asked Answered
G

2

6

Is it possible to take an HTTPServletRequest away from its thread, dissolve this thread (i.e. bring it back to the pool), but keep the underlying connection with the browser working, until I get the results from a time-consuming operation (say, processing an image)? When the return data are processed, another method should be called asynchronously, and be given the request as well as the data as parameters.

Usually, long pooling functions in a pretty blocking fashion, where the current thread is not dissolved, which reduces the scalability of the server-side app, in terms of concurrent connections.

Gudgeon answered 10/11, 2011 at 15:24 Comment(1)
Did you try Servlet 3.0 and it's Asynchronous Servlet? download.oracle.com/javaee/6/api/javax/servlet/annotation/… It will return your thread to the pool, but allow to process some long-term operation and read user's requestChallis
R
5

Yes, you can do this with Servlet 3.0

Below is the sample to write the alert every 30 secs(not tested).

@WebServlet(async =“true”)
public class AsyncServlet extends HttpServlet {

Timer timer = new Timer("ClientNotifier");

public void doGet(HttpServletRequest req, HttpServletResponse res) {

    AsyncContext aCtx = request.startAsync(req, res);
    // Suspend request for 30 Secs
    timer.schedule(new TimerTask(aCtx) {

        public void run() {
            try{
                  //read unread alerts count
                 int unreadAlertCount = alertManager.getUnreadAlerts(username); 
                  // write unread alerts count
    response.write(unreadAlertCount); 
             }
             catch(Exception e){
                 aCtx.complete();
             }
        }
    }, 30000);
}
}

Below is the sample to write based on an event. The alertManager has to be implemented which notifies AlertNotificationHandler when client has to be alerted.

@WebServlet(async=“true”)
public class AsyncServlet extends HttpServlet {
 public void doGet(HttpServletRequest req, HttpServletResponse res) {
        final AsyncContext asyncCtx = request.startAsync(req, res);
        alertManager.register(new AlertNotificationHandler() {
                   public void onNewAlert() { // Notified on new alerts
                         try {
                               int unreadAlertCount =
                                      alertManager.getUnreadAlerts();
                               ServletResponse response = asyncCtx.getResponse();
                               writeResponse(response, unreadAlertCount);
                               // Write unread alerts count
                         } catch (Exception ex) {
                               asyncCtx.complete();
                               // Closes the response
                         }
                   }
        });
  }
}
Recollect answered 11/11, 2011 at 5:58 Comment(2)
What happens if the user goes to the page, and the async object is created, but then they refresh the page? is another object created? And now will two requests get sent back? Or what if they navigate away from the page? Will the response get sent to outer space? Sorry I'm having trouble wrapping my head around this!Cassino
And in your first example you have a method run() inside another method doGet(). That is new to me. Do you have to do it this way or can you seperate the methods? And does it have to be called run?Cassino
Z
2

Yes, it's possible using Servlet spec ver. 3.0. Implementation I can recommend is Jetty server. See here.

Zenithal answered 10/11, 2011 at 15:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.