java.lang.IllegalStateException:远程端点处于[TEXT_PARTIAL_WRITING]状态,这是被调用方法的无效状态

时间:2017-06-13 17:33:34

标签: java websocket stomp spring-websocket sockjs

我的代码:

myStompClient = new WebSocketStompClient(new SockJsClient(list));
mySession = myStompClient
        .connect(WEBSOCKET_URI, bankHeaders, new StompSessionHandlerAdapter() {
            @Override
            public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
                StompHeaders stompHeadersSubscribe = new StompHeaders();
                stompHeadersSubscribe.setDestination(CONSUMER_TECH_QUEUE);
                session.subscribe(stompHeadersSubscribe, new MyStompFrameHandler());// <-- this line fails
                .....
        }).get(5, TimeUnit.SECONDS);

有时我会在日志中看到:

org.springframework.messaging.MessageDeliveryException: nested exception is java.lang.IllegalStateException: The remote endpoint was in state [TEXT_PARTIAL_WRITING] which is an invalid state for called method, failedMessage=GenericMessage [payload=byte[0], headers={simpMessageType=SUBSCRIBE, stompCommand=SUBSCRIBE, nativeHeaders={destination=[/user/queue/consumer/tech], id=[0]}, simpSubscriptionId=0, simpSessionId=e8a5b506-9c09-1a7b-4674-4aecb6567426, simpDestination=/user/queue/consumer/tech}]
    at org.springframework.messaging.simp.stomp.DefaultStompSession.execute(DefaultStompSession.java:281)
    at org.springframework.messaging.simp.stomp.DefaultStompSession.subscribe(DefaultStompSession.java:312)
    at com.finvale.SimpleBankSimulator$1.afterConnected(SimpleBankSimulator.java:98)
    at org.springframework.messaging.simp.stomp.DefaultStompSession.handleMessage(DefaultStompSession.java:421)
    at org.springframework.web.socket.messaging.WebSocketStompClient$WebSocketTcpConnectionHandlerAdapter.handleMessage(WebSocketStompClient.java:342)
    at org.springframework.web.socket.sockjs.client.AbstractClientSockJsSession.handleMessageFrame(AbstractClientSockJsSession.java:271)
    at org.springframework.web.socket.sockjs.client.AbstractClientSockJsSession.handleFrame(AbstractClientSockJsSession.java:213)
    at org.springframework.web.socket.sockjs.client.WebSocketTransport$ClientSockJsWebSocketHandler.handleTextMessage(WebSocketTransport.java:162)
    at org.springframework.web.socket.handler.AbstractWebSocketHandler.handleMessage(AbstractWebSocketHandler.java:43)
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:110)
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$000(StandardWebSocketHandlerAdapter.java:42)
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:81)
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:78)
    at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:399)
    at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:500)
    at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:295)
    at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:130)
    at org.apache.tomcat.websocket.WsFrameClient.processSocketRead(WsFrameClient.java:79)
    at org.apache.tomcat.websocket.WsFrameClient.access$300(WsFrameClient.java:31)
    at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:137)
    at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:120)
    at sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126)
    at sun.nio.ch.Invoker$2.run(Invoker.java:218)
    at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: The remote endpoint was in state [TEXT_PARTIAL_WRITING] which is an invalid state for called method
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.checkState(WsRemoteEndpointImplBase.java:1224)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.textPartialStart(WsRemoteEndpointImplBase.java:1182)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendPartialString(WsRemoteEndpointImplBase.java:222)
    at org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendText(WsRemoteEndpointBasic.java:49)
    at org.springframework.web.socket.adapter.standard.StandardWebSocketSession.sendTextMessage(StandardWebSocketSession.java:203)
    at org.springframework.web.socket.adapter.AbstractWebSocketSession.sendMessage(AbstractWebSocketSession.java:101)
    at org.springframework.web.socket.sockjs.client.WebSocketClientSockJsSession.sendInternal(WebSocketClientSockJsSession.java:126)
    at org.springframework.web.socket.sockjs.client.AbstractClientSockJsSession.sendMessage(AbstractClientSockJsSession.java:152)
    at org.springframework.web.socket.messaging.WebSocketStompClient$WebSocketTcpConnectionHandlerAdapter.send(WebSocketStompClient.java:383)
    at org.springframework.messaging.simp.stomp.DefaultStompSession.execute(DefaultStompSession.java:278)
    ... 26 more

有时它会发生,有时候 - 不是。

我无法理解原因,请澄清。

2 个答案:

答案 0 :(得分:0)

因为您正试图从许多线程连接到websocket。 您应该在下面使用以下行:

synchronized(session) {
            session.subscribe(stompHeadersSubscribe, new MyStompFrameHandler())
        }

答案 1 :(得分:0)

我遇到了这个问题,并提出了另一种方法,据我所知(这种问题似乎在stackOverflow中报告了大约4次...)。

捕获该错误,如果写入繁忙,请等待一段时间以使其完成,然后重试,如下所示。有想法吗?

static public void write(Session sess, String msg) {
    /*
     * to thwart the error: 'remote endpoint was in state [TEXT_FULL_WRITING] which
     * is an invalid state for called method use basic'
     * try, try again...
     */
    RemoteEndpoint.Basic basicRemote = sess.getBasicRemote();
    int i = 0; // tries...
    boolean bWriteSucceeded = false;
    if (verbose) {
        ; // you know... dump something somewhere...
    }
    if (sess.isOpen()) {
        for (i = 0; i < 10 && !bWriteSucceeded; i++) {
            try {
                // Crap. Sometimes getting this:
                // The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid
                // state for called method
                basicRemote.sendText(msg);
                bWriteSucceeded = true;
            } catch (IOException e) {
                // Enhance the auto-generated catch block to try again...
                // TODO: check for if (e == java.io.EOFException))
                if (i < 10 && !bWriteSucceeded) {
                    msleep(20);
                    System.out.println("Write tried:" + i + "times and failed.");
                    continue;
                } // Admit failure.
                System.out.println("Write failed: " + i + " retries. Dumping stackTrace");
                e.printStackTrace();
            }
        }
    }
    // succeed on first time and say nothing...
    if (bWriteSucceeded && i > 0)
        System.out.println("Write took " + i + " tries to succeed.");
    else
        System.out.println("Write failed after " + i + " retries.");
}

我的msleep版本是:

static void msleep(int ms) {
    try {
        System.out.printf("Sleeping...");
        Thread.sleep(ms);
        } catch (InterruptedException e) {
            System.out.printf("Exception caught");
            }

}