2016-12-12 13 views
0

Tomcatで非同期サーブレットを実装しようとしています。HttpSessionAttributeListener.attributeReplaced()がトリガーされるたびにクライアントに更新を送信します。クライアント側は、サーバー送信イベントを受信するように構成されています。HttpServletとAsyncContextの応答がありません

リスナーは更新を受信しますが、ブラウザは応答を受信しません。ブラウザの開発区画には、要求がpendingであり、AsyncContext.setTimeout()で設定されたタイムアウト後にエラー500で終了することが示されています。私はアイデアがなくなり、なぜこれが起きているのですか?

JS

var source = new EventSource('/acount/sse'); 

source.onmessage = function (event) { 
    console.log(event.data); 
    document.querySelector('#messageArea p').innerHTML += event.data; 
}; 

そして、これは私のサーブレットのコードです:

サーブレット

public class SSE extends HttpServlet implements HttpSessionAttributeListener { 

    public static final String ATTR_ENTRY_PROCESSOR_PROGRESS = "entryProcessorProgress"; 

    private AsyncContext aCtx; 

    @Override 
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 

     req.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true); 

     resp.setContentType("text/event-stream"); 
     resp.setHeader("Cache-Control", "no-cache"); 
     resp.setHeader("Connection", "keep-alive"); 
     resp.setCharacterEncoding("UTF-8"); 

     aCtx = req.startAsync(req, resp); 
     aCtx.setTimeout(80000); 

    } 

    @Override 
    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) { 
     write(httpSessionBindingEvent); 
    } 

    @Override 
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) { 

    } 

    @Override 
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) { 
     write(httpSessionBindingEvent); 
    } 

    private void write(HttpSessionBindingEvent httpSessionBindingEvent) { 
     if (httpSessionBindingEvent.getName().equals(ATTR_ENTRY_PROCESSOR_PROGRESS)) { 
      try { 
       String message = "data: " + httpSessionBindingEvent.getValue() + "\n\n"; 
       aCtx.getResponse().getWriter().write(message); 
       aCtx.getResponse().getWriter().flush(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

     } 
    } 


} 

答えて

0

問題:

私はあなたのコードを試してみました、java.lang.NullPointerExceptionがにあった

:ACTXがnullであるので

aCtx.getResponse().getWriter().write(message); 

サーブレットとリスナーが混在していますが、リスナーメソッドが呼び出されたときに、AsyncContextの初期化は行われません。したがって、nothingsはブラウザに行きます。

サーブレットのリスナーにコードを分割し、セッション属性を使用してAsychContextオブジェクトを密輸しました。それはリスナーからアクセス可能でした。

これは機能します。

完全なコード:

HTML:

<!DOCTYPE html> 
<html> 
<head> 
<meta charset="UTF-8"> 
<title>Server Event Listener</title> 
</head> 
<body> 
<div id="messageArea"> 
<p></p> 
</div> 
<script> 
var source = new EventSource('/yourPath/ServerSentEvent'); 

source.onmessage = function (event) { 
    console.log(event.data); 
    document.querySelector('#messageArea p').innerHTML += event.data; 
}; 
</script> 
</body> 
</html> 

サーブレット:

package testingThings.ServerSentEvent; 

import java.io.IOException; 

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(asyncSupported = true, value = {"/ServerSentEvent"}) 
public class ServerSentEvent extends HttpServlet { 
    private static final long serialVersionUID = 1L; 

    @Override 
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 

     // add @WebServlet(asyncSupported = true) instead 
     // http://stackoverflow.com/questions/7855712/how-to-avoid-request-set-async-supported-true-to-enable-async-servlet-3-0-proces 
     // req.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true); 

     resp.setContentType("text/event-stream"); 
     resp.setHeader("Cache-Control", "no-cache"); 
     resp.setHeader("Connection", "keep-alive"); 
     resp.setCharacterEncoding("UTF-8"); 

     AsyncContext aCtx = req.startAsync(req, resp); 
     aCtx.setTimeout(80000); 

     // add a asyncContext a session Attribute 
     req.getSession().setAttribute("asyncContext", aCtx); 

     //start logging in listener 
     req.getSession().setAttribute("entryProcessorProgress", "trigger output"); 
    } 
} 

HttpSessionAttributeListenerに:

package testingThings.ServerSentEvent; 

import java.io.IOException; 

import javax.servlet.AsyncContext; 
import javax.servlet.annotation.WebListener; 
import javax.servlet.http.HttpSessionAttributeListener; 
import javax.servlet.http.HttpSessionBindingEvent; 

@WebListener 
public class SessionAttributeListener implements HttpSessionAttributeListener { 

    public static final String ATTR_ENTRY_PROCESSOR_PROGRESS = "entryProcessorProgress"; 

    @Override 
    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) { 
     write(httpSessionBindingEvent); 
    } 

    @Override 
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) { 

    } 

    @Override 
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) { 
     write(httpSessionBindingEvent); 
    } 

    private void write(HttpSessionBindingEvent httpSessionBindingEvent) { 
     if (httpSessionBindingEvent.getName().equals(ATTR_ENTRY_PROCESSOR_PROGRESS)) { 
      try { 
       // get the AsyncContext from the session 
       AsyncContext aCtx = (AsyncContext) httpSessionBindingEvent.getSession().getAttribute("asyncContext"); 
       String message = "data: " + httpSessionBindingEvent.getValue() + "<br>\n\n"; 
       aCtx.getResponse().getWriter().write(message); 
       aCtx.getResponse().getWriter().flush(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 
+1

ありがとう、それは魅力のように動作します! –

関連する問題