集成CDI和WebSockets
考慮嘗試一個簡單的Java EE 7原型應用程序,該應用程序涉及JAX-RS(REST),WebSockets和CDI。
注意 :不想讓它成為破壞者-但這篇文章主要討論了我在嘗試使用Web套接字和使用CDI作為“膠水”的REST(在Java EE應用程序中)時遇到的問題。 整合并未實現,但是仍然吸取了一些教訓:-)
這個想法是使用REST端點作為Web套接字端點的“提要”,從而將數據“推”到所有連接的客戶端:
- JAX-RS端點,它從其他來源接收數據(可能是實時的)作為Web套接字端點的輸入
- 使用CDI事件作為黑白JAX-RS和WebSocket端點的粘合劑,并“觸發”有效負載 @Path("/feed") public class RESTFeed {@InjectEvent<String> event;@POST@Consumes(MediaType.TEXT_PLAIN)public void push(String msg) {event.fire(msg);} }
- 在WebSocket端點實現中使用CDI Observer方法將數據推送到連接的客戶端: public void onMsg(@Observes String msg) {//different WS enpoint instance - notice the hash code value in the server logSystem.out.println("WS End point class ID -- " + this.hashCode());try {client.getBasicRemote().sendText(msg);} catch (IOException ex) {Logger.getLogger(ServerEndpoint.class.getName()).log(Level.SEVERE, null, ex);} }
當然,目前還沒有考慮到更詳細的信息,例如性能,異步通信等。 更多實驗
但這有可能嗎?
這是我執行的步驟
- 部署代碼
- 瀏覽到http:// localhost:8080 / Explore-WebSocket-CDI-Integration-Maven /并作為Web套接字客戶端連接
- 使用Postman在REST端點上觸發HTTP POST請求
繁榮! Observer方法中的NullPointerException –我等待了幾秒鐘,然后現實擊中了我!
根本原因(據我了解)
- WebSocket端點的行為
WebSocket端點與JAX-RS資源類相似,因為每個連接的客戶端都有一個Web套接字端點類的實例(至少默認情況下)。 WebSocket規范中明確提到了這一點。 客戶端(對等方)連接后,便會創建一個唯一的實例,并且可以安全地將Web套接字會話對象(對等方的表示形式)作為實例變量進行緩存。 IMO,這是一個簡單干凈的編程模型
- 但是CDI容器還有其他計劃!
REST端點一旦觸發CDI事件(響應POST請求),CDI容器就會創建WebSocket終結點(在本例中為CDI Observer)的其他實例。 為什么? 因為CDI bean本質上是上下文相關的 。 該應用程序不控制CDI bean的實例。 它只是使用它們(通過@Inject)。 由容器來創建和銷毀bean實例,并確保在相同上下文中執行的bean可以使用適當的實例。 容器如何確定上下文呢? 通過范圍 –應用程序,會話,請求等…..
(再次,在CDI規范中明確提到)
因此,問題的要點是沒有WebSocket終結點當前上下文的實例–因此,CDI將創建一個新實例以傳遞消息。 當然,這意味著實例變量將指向null,因此將指向NPE(Duh!)
。
WebSocket端點將使用哪個CDI范圍? 我嘗試了@ ApplicationScoped,@ SessionScoped和@RequestScoped卻沒有太多運氣–仍然是一個新實例和一個NPE
還有其他選擇嗎?
- 將會話集定義為靜態變量將達到目的: private static Set<Session> peers = Collections.synchronizedSet(new HashSet());
但是,如果僅在觀察者方法中需要處理客戶端特定狀態(只能作為實例變量處理)的情況下,IMO只是一種黑客手段,這是不可行的–它勢必會保持未初始化的狀態。
- 服務器發送事件 ? 但是最終,SSE!= WebSocket。 如果用例要求“僅”服務器端推送,則可以選擇使用。 SSE尚未成為Java EE標準-Java EE 8可能使之成為可能
解決方法
我不是專家,但是我想這取決于WebSocket規范,以便更清楚地說明如何將其與CDI結合使用。 鑒于CDI是Java EE規范中必不可少的一部分,因此將其與其他規范(特別是以HTML5為中心的規范,例如JAX-RS,WebSocket等)進行無縫集成非常重要。
Bruno Borges的這篇文章鏈接到與JMS,CDI和WebSocket以及它們如何相互集成有關的類似問題。
我錯過了明顯的事情嗎? 您有什么建議/解決方案嗎? 請隨時鳴叫! :-)
示例代碼在GitHub上可用 (以供您查看)。 我在GlassFish 4.1和Wildfly 8.2.0上嘗試過
我想現在就這些了。 :-)
干杯!
翻譯自: https://www.javacodegeeks.com/2015/02/integrating-cdi-websockets.html
總結
以上是生活随笔為你收集整理的集成CDI和WebSockets的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中的XSL转换:一种简单的方法
- 下一篇: 电脑双斜杠怎么打出来(电脑中双斜杠怎么打