0

I'm making a web based scoring system for a robotic competition. When a point is scored, I want to refresh the page of everybody watching the game. My code is working "correctly".

My problem is that when I test and I open about 5 to 10 web pages, any other pages that I request are not processed until I close some pages. I think that what's happening is that request.startAsync() is not releasing the thread and it's waiting infinitely.

I've tested on both Jetty 9.2.7.v20150116 and Tomcat7. Both have the same slow behavior.

// Display a game with all it's events
// http://stackoverflow.com/questions/10878243/sse-and-servlet-3-0

@WebServlet(urlPatterns = { "/gameRefresh" }, asyncSupported = true)
public class GameRefreshController extends HttpServlet 
{
    private static final long serialVersionUID = -6890088129187673292L;

    private static AtomicBoolean refreshNeeded = new AtomicBoolean();

    private final Queue<AsyncContext> ongoingRequests = new ConcurrentLinkedQueue<>();
    private ScheduledExecutorService service;

    public static void setRefreshNeeded(boolean value)
    {
        refreshNeeded.set(value);
    }

    @Override
    public void init(ServletConfig config) throws ServletException 
    {
        final Runnable notifier = new Runnable() 
        {
            @Override
            public void run() 
            {
                // Don't refresh if it's not needed.
                if(!refreshNeeded.get())
                {
                    return;
                }
                // This var is set by the backend when an event occurs.
                setRefreshNeeded(false);

                final Iterator<AsyncContext> iterator = ongoingRequests.iterator();
                // not using for : in to allow removing items while iterating
                while (iterator.hasNext()) 
                {
                    AsyncContext asyncContext = iterator.next();
                    final ServletResponse servletResponse = asyncContext.getResponse();
                    PrintWriter out;
                    try 
                    {
                        out = servletResponse.getWriter();
                        String toOutput = "data: refresh\n\n";
                        out.write(toOutput);
                        out.checkError();
                    } 
                    catch(IOException exception)
                    {
                        // iterator is always removed because we refresh the whole page.
                    }
                    finally
                    {
                        iterator.remove();
                    }
                }
            }
        };
        service = Executors.newScheduledThreadPool(1);
        service.scheduleAtFixedRate(notifier, 1, 1, TimeUnit.SECONDS);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
    {
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("UTF-8");
        request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
        final AsyncContext asyncContext = request.startAsync();
        asyncContext.setTimeout(0);
        asyncContext.addListener(new AsyncListener() 
        {
            @Override
            public void onComplete(AsyncEvent event) throws IOException 
            {
                ongoingRequests.remove(asyncContext);
            }

            @Override
            public void onTimeout(AsyncEvent event) throws IOException 
            {
                ongoingRequests.remove(asyncContext);
            }

            @Override
            public void onError(AsyncEvent event) throws IOException 
            {
                ongoingRequests.remove(asyncContext);
            }

            @Override
            public void onStartAsync(AsyncEvent event) throws IOException 
            {
            }
        });
        ongoingRequests.add(asyncContext);
    }
}
Joakim Erdfelt
  • 46,896
  • 7
  • 86
  • 136
fjoanis
  • 277
  • 2
  • 8
  • 1
    Sounds like you are hitting the browsers own per-host connection limits. Test with multiple machines, or multiple network interfaces to get around that. – Joakim Erdfelt Feb 09 '15 at 15:17
  • You are right, this thread confirm what you're telling me : http://stackoverflow.com/questions/985431/max-parallel-http-connections-in-a-browser Thanks a lot Joakim. – fjoanis Feb 11 '15 at 03:32

0 Answers0