2014-10-30 20 views
1

我看到很多關於如何使用某種嵌入式web服務器設置JSR356 websockets的教程。如何在碼頭容器中安裝JSR356 websockets

但是我想添加一些websockets到部署到獨立碼頭安裝的現有WAR,jetty jetty-9.2.3.v20140905,我可以在這裏找到很少的信息。我無法弄清楚是什麼阻止它的工作。據我瞭解,註釋的服務器端點應該由jetty自動處理。

ServerEndpoint:

@ServerEndpoint(value = "/myendpoint") 
public class MyServerEndpoint {  
    private Logger logger = Logger.getLogger(this.getClass().getName());  

    @OnOpen 
    public void onOpen(Session s) { 
     logger.info("Server Connected ... " + s.getId()); 
     s.getAsyncRemote().sendText("You are connected to the websocket server"); 
    }   

    @OnMessage 
    public void onMessage(String message, Session session) { 

     // Sent the message back to all connected users    
     logger.info("Server Session " + session + " Received string message " + message); 

     for(Session s: session.getOpenSessions()) {  
      if (s.isOpen()) { 
       s.getAsyncRemote().sendText(message + " server response"); 
      }  
     } 
    }   

    @OnClose  
    public void onClose(Session session, CloseReason reason) { 
     logger.info("Server Session " + session + " closed for reason " + reason); 
    } 
} 

ClientEndpoint:

@ClientEndpoint 
public class MyClientEndpoint {  
    private Logger logger = Logger.getLogger(this.getClass().getName());  

    @OnOpen 
    public void onOpen(Session s) { 
     logger.info("Client Connected ... " + s.getId()); 
     s.getAsyncRemote().sendText("hello from the client!"); 
    }   

    @OnMessage 
    public void onMessage(String message, Session session) { 

     logger.info("Client Session " + session + " Received string message " + message);  

    }   

    @OnClose  
    public void onClose(Session session, CloseReason reason) { 
     logger.info("Client Session " + session + " closed for reason " + reason); 
    } 
} 

下面是代碼(一些現有的方法中運行)的客戶端連接到服務器

WebSocketContainer container = ContainerProvider.getWebSocketContainer(); 
    String uri = "ws://localhost:8080/myWar/myendpoint"; 
    container.connectToServer(MyClientEndpoint.class, URI.create(uri)); 

但旋轉起來jetty在connectToServer行上發出錯誤

2014-10-30 12:26:58.658:WARN:oeja.ServletContainerInitializersStarter:main: 
org.eclipse.jetty.websocket.api.InvalidWebSocketException: Unable to instantiate websocket: class java.lang.Class 
at org.eclipse.jetty.websocket.jsr356.ClientContainer.newClientEndpointInstance(ClientContainer.java:311) 
    at org.eclipse.jetty.websocket.jsr356.ClientContainer.connectToServer(ClientContainer.java:172) 

我能想到的只是URI不正確。如果碼頭在8080上運行,我的.war被命名爲myWar,並且我的終點被命名爲myendpoint ...是不是正確的URI?

是否需要執行一些額外步驟才能激活服務器端點以偵聽連接?我必須失去一些明顯的東西。

回答

1

奇怪的是,你的錯誤信息。

org.eclipse.jetty.websocket.api.InvalidWebSocketException: 
    Unable to instantiate websocket: class java.lang.Class 

表示websocket實現已交給原始java.lang.Class實例化。 這不起作用。

這也意味着沒有嘗試連接,因爲WebSocket類本身很糟糕,連接是不可能的。

下面是一個簡短的(有效且有效的)示例,顯示了它的用法。

package jetty.jsr356; 

import java.io.IOException; 
import java.net.URI; 
import java.util.concurrent.CountDownLatch; 

import javax.websocket.ClientEndpoint; 
import javax.websocket.CloseReason; 
import javax.websocket.CloseReason.CloseCodes; 
import javax.websocket.ContainerProvider; 
import javax.websocket.OnClose; 
import javax.websocket.OnMessage; 
import javax.websocket.OnOpen; 
import javax.websocket.Session; 
import javax.websocket.WebSocketContainer; 

@ClientEndpoint 
public class TestClientAnnotatedClass 
{ 
    private static CountDownLatch closeLatch = new CountDownLatch(1); 

    @OnOpen 
    public void onOpen(Session session) 
    { 
     System.out.println("@OnOpen - " + session); 
     try 
     { 
      session.getBasicRemote().sendText("Rock it with Java WebSocket"); 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    @OnMessage 
    public void onMessage(Session session, String msg) 
    { 
     System.out.println("@OnMessage - ["+msg+"]"); 
     try 
     { 
      session.close(new CloseReason(CloseCodes.NORMAL_CLOSURE,"Thanks")); 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    @OnClose 
    public void onClose(CloseReason close) 
    { 
     System.out.println("@OnClose - " + close); 
     closeLatch.countDown(); 
    } 

    public static void main(String[] args) 
    { 
     try 
     { 
      WebSocketContainer ws = ContainerProvider.getWebSocketContainer(); 

      ws.connectToServer(TestClientAnnotatedClass.class,new URI("ws://echo.websocket.org/?encoding=text")); 
      closeLatch.await(); 
     } 
     catch (Throwable t) 
     { 
      t.printStackTrace(); 
     } 
    } 
} 

你會看到類似這樣的

2014-10-30 11:34:19.197:INFO::main: Logging initialized @71ms 
@OnOpen - WebSocketSession[websocket=JsrAnnotatedEventDriver[[email protected]],behavior=CLIENT,[email protected]{IDLE}{f=Flusher[queueSize=0,aggregateSize=0,failure=null],g=Generator[CLIENT,validating],[email protected][ExtensionStack,s=START,c=0,len=0,f=null,[email protected][behavior=CLIENT,maxTextMessageSize=65536,maxTextMessageBufferSize=32768,maxBinaryMessageSize=65536,maxBinaryMessageBufferSize=32768,asyncWriteTimeout=60000,idleTimeout=300000,inputBufferSize=4096]]},[email protected][batching=true],incoming=JsrAnnotatedEventDriver[[email protected]],outgoing=ExtensionStack[queueSize=0,extensions=[],incoming=org.eclipse.jetty.websocket.jsr356.JsrSession,outgoing=org.eclipse.jetty.websocket.client.io.WebSocketClientConnection]] 
@OnMessage - [Rock it with Java WebSocket] 
@OnClose - CloseReason[1000,Thanks] 
+0

謝謝。然而,我得到了同樣的錯誤。 org.eclipse.jetty.websocket.api.InvalidWebSocketException:無法實例化websocket:java.lang.Class類 我想知道如果問題是以某種方式與我的碼頭安裝,而不是我使用的代碼。我把'main'函數的代碼放到了我的war文件中的另一個函數中,這應該沒有什麼區別? – user2197116 2014-10-30 22:07:01

+1

讓我看看我是否可以爲您搭建一個示例項目。 – 2014-10-30 23:50:55

0

碼頭輸出創建使用反射(見/jetty/websocket/jsr356/ClientContainer#newClientEndpointInstance())註釋客戶端點的實例,但Java是無法實例化一個非靜態內部類的方式。實際的原因異常類似於java.lang.NoSuchMethodException: <pkg>.OuterClass$InnerClass.<init>(),但它被吞下。

解決方案:帶註釋的端點類不應嵌套或嵌套靜態(內部)類。