2014-07-13 55 views
1

我正在嘗試編寫一個測試用例,它創建一個套接字並連接到嵌入式jetty實例。我使用在嵌入式Jetty上使用javax.websocket進行JUnit測試拋出RejectedExecutionException:NonBlockingThread

  • 碼頭:9.2.0.RC0
  • javax.websocket-API & javax.websocket客戶端的API:1.0
  • javax.websocket服務器&客戶IMPL:9.1.5。 v20140505

用websocket servlet啓動嵌入式jetty服務器似乎工作正常。我從this example獲取了一些代碼。但是這條線

... 
container.connectToServer(SocketClient.class, uri); 
... 

引發此異常

java.io.IOException: java.util.concurrent.RejectedExecutionException: [email protected] 
    at org.eclipse.jetty.websocket.client.WebSocketClient.initialiseClient(WebSocketClient.java:462) 
    at org.eclipse.jetty.websocket.client.WebSocketClient.connect(WebSocketClient.java:187) 
    at org.eclipse.jetty.websocket.jsr356.ClientContainer.connect(ClientContainer.java:135) 
    at org.eclipse.jetty.websocket.jsr356.ClientContainer.connectToServer(ClientContainer.java:172) 
    at com.playquickly.socket.SocketClient.connect(SocketClient.java:18) 
    at com.playquickly.servlet.SocketServletTest.testSocket(SocketServletTest.java:50) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
    at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48) 
    at org.junit.rules.RunRules.evaluate(RunRules.java:20) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67) 
Caused by: java.util.concurrent.RejectedExecutionException: [email protected] 
    at org.eclipse.jetty.util.thread.QueuedThreadPool.execute(QueuedThreadPool.java:361) 
    at org.eclipse.jetty.io.SelectorManager.execute(SelectorManager.java:122) 
    at org.eclipse.jetty.io.SelectorManager.doStart(SelectorManager.java:207) 
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) 
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132) 
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114) 
    at org.eclipse.jetty.websocket.client.io.ConnectionManager.doStart(ConnectionManager.java:200) 
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68) 
    at org.eclipse.jetty.websocket.client.WebSocketClient.initialiseClient(WebSocketClient.java:454) 
    ... 30 more 

這是我陳述嵌入式Jetty服務器包裝。

public class EmbeddedJetty { 

    private final Logger LOG = Logger.getLogger(EmbeddedJetty.class.getSimpleName()); 

    private final int port; 
    private Server server; 

    public EmbeddedJetty(int port) { 
     this.port = port; 
    } 

    public void start() throws Exception { 
     server = new Server(); 
     ServerConnector connector = new ServerConnector(server); 
     connector.setPort(8080); 
     server.addConnector(connector); 

     // Setup the basic application "context" for this application at "/" 
     // This is also known as the handler tree (in jetty speak) 
     ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); 
     context.setContextPath("/"); 
     server.setHandler(context); 

     try { 
      // Initialize javax.websocket layer 
      ServerContainer wscontainer = WebSocketServerContainerInitializer.configureContext(context); 

      // Add WebSocket endpoint to javax.websocket layer 
      wscontainer.addEndpoint(SocketServlet.class); 
      System.out.println("Begin start"); 
      server.start(); 
      System.out.println("End start"); 
     } catch (Throwable t) { 
      t.printStackTrace(System.err); 
     } 
    } 

    public void stop() throws Exception { 
     server.stop(); 
     LOG.info("Jetty server stopped"); 
    } 
} 

客戶端點

@ClientEndpoint(encoders = {MessageCoder.class}, decoders = {MessageCoder.class}) 
public class SocketClient { 

    public static Session connect(URI uri) throws Exception { 
     WebSocketContainer container = ContainerProvider.getWebSocketContainer(); 

     try { 
      // Attempt Connect 
      return container.connectToServer(SocketClient.class, uri); 
     } finally { 
      // Force lifecycle stop when done with container. 
      // This is to free up threads and resources that the 
      // JSR-356 container allocates. But unfortunately 
      // the JSR-356 spec does not handle lifecycles (yet) 
      if (container instanceof LifeCycle) { 
       ((LifeCycle) container).stop(); 
      } 
     } 
    } 

    @OnMessage 
    public void onMessage(Message msg, Session session) { 
     System.out.println(session.getId() + ": " + msg.toString()); 
    } 


} 

而且測試

public class SocketServletTest { 

    private static EmbeddedJetty server; 

    @ClassRule 
    public static final ExternalResource integrationServer = new ExternalResource() { 
     @Override 
     protected void before() throws Throwable { 
      System.out.println("Starting..."); 
      server = new EmbeddedJetty(8080); 
      server.start(); 
      System.out.println("Started"); 
     } 
    }; 


    @Before 
    public void setUp() throws Exception { 

    } 

    @After 
    public void shutdown() throws Exception { 
     server.stop(); 
    } 

    @Test 
    public void testSocket() throws Exception { 
     URI uri = server.getWebsocketUri(SocketServlet.class); 

     Session s1 = SocketClient.connect(uri); 
    } 

} 

回答

3

不要混用碼頭的版本。

這是JSR-356 API設計的不幸副作用。 (客戶端實現是根實現,服務器實現建立在該實現之上)

客戶端容器按每個JVM初始化,並且每個服務器容器都根據webapp進行初始化。

您的堆棧跟蹤不碼頭9.2.0.RC0爲您指示(行號關閉)

https://github.com/eclipse/jetty.project/blob/jetty-9.2.0.RC0/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/ConnectionManager.java#L200

他們似乎是從碼頭9.1.5.v20140505

https://github.com/eclipse/jetty.project/blob/jetty-9.1.5.v20140505/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/ConnectionManager.java#L200

無處不在使用Jetty 9.2.2.v20140723。

此外,使用這個版本意味着你可以擺脫finally container.stop()黑客。

+0

使用相同的碼頭版本肯定有幫助,謝謝。儘管現在我正在努力從服務器發送到客戶端,因爲測試結束了,連接顯然已關閉。你有什麼技巧可以爲我的socket服務器編寫一些集成測試嗎? 謝謝你的時間。 –

相關問題