Tarefa assíncrona Servlet 3 no Tomcat 7

Estou tentando implementar o bate-papo simples usando o padrão Servlet 3.0 e Comet com base em seu suporte asynchronous.

Estou inspirado por este artigo: http://www.javaworld.com/javaworld/jw-02-2009/jw-02-servlet3.html?page=3

Meu servlet se parece com isso.

@WebServlet(name="chatServlet", urlPatterns={"/ChatServlet"}, asyncSupported=true) public class ChatServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { AsyncContext aCtx = request.startAsync(request, response); ServletContext appScope = request.getServletContext(); List watchers = (List) appScope.getAttribute("watchers"); watchers.add(aCtx); //register the watcher } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { AsyncContext aCtx = request.startAsync(request, response); ServletContext appScope = request.getServletContext(); Queue messages = (Queue)appScope.getAttribute("messages"); messages.add(someMessage); } } 

agora meu ouvinte se parece com isso:

 @WebListener public class ChatPushService implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { final List watchers = new ArrayList(); sce.getServletContext().setAttribute("watchers", watchers); // store new messages not published yet Queue messages = new ConcurrentLinkedQueue(); sce.getServletContext().setAttribute("messages", messages); Executor messageExecutor = Executors.newCachedThreadPool(); final Executor watcherExecutor = Executors.newCachedThreadPool(); while(true) { if(!messages.isEmpty()) { System.out.println("notEmpty"); String message = messages.poll(); messageExecutor.execute(new Runnable(){ @Override public void run() { for(final AsyncContext aCtx : watchers){ watcherExecutor.execute(new Runnable(){ @Override public void run() { try { aCtx.getResponse().getWriter().print("brrrrr"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } } }); } } } } 

Quando eu estou começando meu está congelando durante o início do contêiner.

 Nov 1, 2011 1:12:09 AM org.apache.catalina.core.AprLifecycleListener init INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server:/usr/lib/jvm/java-6-openjdk/jre/lib/amd64:/usr/lib/jvm/java-6-openjdk/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib/jni:/lib:/usr/lib Nov 1, 2011 1:12:09 AM org.apache.tomcat.util.digester.SetPropertiesRule begin WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:Servlet3Comet' did not find a matching property. Nov 1, 2011 1:12:09 AM org.apache.coyote.AbstractProtocol init INFO: Initializing ProtocolHandler ["http-bio-8080"] Nov 1, 2011 1:12:09 AM org.apache.coyote.AbstractProtocol init INFO: Initializing ProtocolHandler ["ajp-bio-8009"] Nov 1, 2011 1:12:09 AM org.apache.catalina.startup.Catalina load INFO: Initialization processed in 624 ms Nov 1, 2011 1:12:09 AM org.apache.catalina.core.StandardService startInternal INFO: Starting service Catalina Nov 1, 2011 1:12:09 AM org.apache.catalina.core.StandardEngine startInternal INFO: Starting Servlet Engine: Apache Tomcat/7.0.22 

Parece que public void contextInitialized function não está sendo executada de forma assíncrona no plano de fundo e está bloqueando a boot de contêiner adicional.

Por quê?

Alguém pode me ajudar nessa questão?

Você está executando enquanto loop dentro do método contextInitialized () que está errado. contextInitialized () é invocado pelo Servlet Container como parte da boot do aplicativo, tendo o loop while bloqueando o início do aplicativo.

Modificado o código, tal como o ContextListener irá iniciar um thread daemon que publica as mensagens para os observadores

 @WebListener public class ChatPushService implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { final List watchers = new ArrayList(); sce.getServletContext().setAttribute("watchers", watchers); // store new messages not published yet Queue messages = new ConcurrentLinkedQueue(); sce.getServletContext().setAttribute("messages", messages); new chatManager(sce.getServletContext()).start(); //START DAEMON } } public class ChatManager implements Runnable { ServletContext servletCtx; public ChatManager(ServletContext ctx) { this.servletCtx = ctx; } public void run() { List watchers = (List) servletCtx.getAttribute("watchers"); Queue messages = (Queue)appScope.getAttribute("messages"); Executor messageExecutor = Executors.newCachedThreadPool(); final Executor watcherExecutor = Executors.newCachedThreadPool(); while(true) { if(!messages.isEmpty()) { System.out.println("notEmpty"); String message = messages.poll(); messageExecutor.execute(new Runnable(){ @Override public void run() { for(final AsyncContext aCtx : watchers){ watcherExecutor.execute(new Runnable(){ @Override public void run() { try { aCtx.getResponse().getWriter().print("brrrrr"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } } }); } } } } 

Eu não posso comentar sobre o código de Ramesh, então eu tenho que colocá-lo aqui … Já que nenhum thread envolve o ChatManager, eu acredito que você deveria chamar run () e não start (). Também, bastante óbvio, deve ser novo ChatManager () .. não novo chatManager () … conta de Java foi sensível a maiúsculas e minúsculas.

Intereting Posts