Flush in asynchronous Servlet does not work

Asked

Viewed 126 times

1

I am studying for web certification, and came across a problem while trying to make a chat using long pooling, but precisely in the article:

http://blog.caelum.com.br/javaee-6-contexto-assincrono-das-servlets-para-o-ajax-push/

I noticed that my client was not getting writing, so I wrote a basic example to see if the answer was written without the oncomplete() in asynchronous context, but I noticed that it didn’t work in Chrome by locking the browser, but in firefox and IE it worked, so the question is:

In this code below the customer should get the answer or there is some error on my part?

package br.com.claudemir.livroCert;
import java.io.IOException;

import javax.servlet.AsyncContext;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
@WebServlet(asyncSupported=true,urlPatterns={"/MyServlet"})
public class MyServlet extends GenericServlet {
    private static final long serialVersionUID = 1L;
    public MyServlet() {
        super();
    }
    @Override
    public void service(ServletRequest req, ServletResponse resp)
            throws ServletException, IOException {
        AsyncContext ac = req.startAsync();
        ac.setTimeout(0);
        MyAsincTask t = new MyAsincTask(ac);
        ac.start(t);
    }

}

Task

package br.com.claudemir.livroCert;

import java.io.IOException;

public class MyAsincTask implements Runnable {
    private javax.servlet.AsyncContext context;
    public MyAsincTask(javax.servlet.AsyncContext context) {
        this.context = context;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(3000);
            javax.servlet.ServletResponse resp = context.getResponse();
            resp.getWriter().println("oim");
            resp.getWriter().flush();
        } catch (InterruptedException | IOException e) {
            e.printStackTrace();
        }
    }

}

My code is this::

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    <script type="text/javascript" src="jquery-2.1.3.js"></script>
    <script type="text/javascript" src="jquery.tmpl.min.js"></script>
    <script type="text/javascript">
    $(document).ready(function(){
        $("#btn_enviar").click(function(event) {
            event.preventDefault();
        $.ajax({

            url: 'subscribe',
            data: '{}',
            type: 'GET',
            success: function(data){
                alert("resposta server");
            }
        });     
    });
        $("#btn_postar").click(function(event) {
            event.preventDefault();
        $.ajax({

            url: 'subscribe',
            data: '{}',
            type: 'POST',

            success: function(data){
                alert("post mensagem");
            }
        });     
    });

    });
    </script>
    </head>
    <body>
    <form>
    Entrar no Chat:<br />
    <input type="button" id="btn_enviar" value="entrar" /></br>
    <input type="button" id="btn_postar" value="postar" /></br>
    <input type="button" id="btn_postar_simples" value="postar simples" /></br>

    </form>
    </body>
    </html>

Servlet:

package br.com.claudemir;

import java.io.IOException; 
import java.io.PrintWriter;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = { "/subscribe" }, asyncSupported = true, loadOnStartup = 1)
public class ChatServlet extends HttpServlet {

    private Queue<AsyncContext> clients = new ConcurrentLinkedQueue<AsyncContext>();
    private BlockingQueue<String> messages = new LinkedBlockingQueue<String>();
    private AtomicInteger contador = new AtomicInteger();
    private AtomicInteger clientes = new AtomicInteger();

    @Override
    public void init() throws ServletException {
        final ExecutorService executors = Executors.newCachedThreadPool();
        Executors.newSingleThreadExecutor().execute(new Runnable() {
            public void run() {
                while (true) {
                    try {
                        final String message = messages.take();

                        for (final AsyncContext ctx : clients) {
                            executors.execute(new Runnable() {
                                public void run() {
                                    try {
                                        PrintWriter writer = ctx.getResponse()
                                                .getWriter();
                                        System.out.println(message);
                                        writer.println(message);
                                        writer.flush();
                                        //ctx.complete();
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                }

                            });
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        });
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setContentType("text/html");
     // Set to expire far in the past.
        resp.setHeader("Expires", "Sat, 6 May 1995 12:00:00 GMT");

        // Set standard HTTP/1.1 no-cache headers.
        resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");

        // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
        resp.addHeader("Cache-Control", "post-check=0, pre-check=0");

        // Set standard HTTP/1.0 no-cache header.
        resp.setHeader("Pragma", "no-cache");
        AsyncContext ctx = req.startAsync();
        ctx.setTimeout(3000000);
        clients.add(ctx);
        System.out.println("novo cliente. id: " + clientes.incrementAndGet());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setContentType("text/html");
        System.out.println("enviando mensagem para   " + clientes + " clientes");
        messages.add(String.format("mensagem número %d %n", contador.incrementAndGet()));
    }
}
insira o código aqui

This client was made to test the flush if I do ctx.complete, the writing happens in all those who did get, but only if I give a complete, but this way I disconnect the client, and then I would have to make a new get.

In the first code has no client list implementation, in case the first doubt worked after setar

resp.setContentType("text/html");

But now, in the code that I’m actually implementing from the chat, I’m having this problem, I might actually have to give the ctx.complete(), but I find it strange to have to re-enter the chat every time and the Git source does not have the complete.

  • Claudemir, welcome to [en.so]! There seems to be no problem with its implementation. You could post the client code that runs in the browser?

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.