Tomcat 8.0.23 を使用して websocket 接続を終了しています。着信メッセージを処理する次のコードがあります。
@OnMessage
public void onMsg(Session session, byte[] request) {
executorService.execute(() ->
session.getAsyncRemote().sendBinary(
ByteBuffer.wrap(getResponse(session, request)), result -> {
if (!result.isOK()) {
LOGGER.catching(result.getException());
}
}
));
}
しかし、次の例外が発生します。
Exception in thread "pool-6-thread-10160" java.lang.IllegalStateException: The remote endpoint was in state [BINARY_FULL_WRITING] which is an invalid state for called method
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.checkState(WsRemoteEndpointImplBase.java:1148)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.binaryStart(WsRemoteEndpointImplBase.java:1101)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendBytesByCompletion(WsRemoteEndpointImplBase.java:152)
at org.apache.tomcat.websocket.WsRemoteEndpointAsync.sendBinary(WsRemoteEndpointAsync.java:65)
同じセッションに同時に書き込もうとすると、Tomcat がその例外をスローしているようです。
エラーはこのメソッドから来ています:
private void checkState(State... required) {
for (State state : required) {
if (this.state == state) {
return;
}
}
throw new IllegalStateException(
sm.getString("wsRemoteEndpoint.wrongState", this.state));
}
java docに基づいているため、 sendBinary がその例外をスローするとは思っていませんでした:
sendBinary void sendBinary(ByteBuffer データ、SendHandler ハンドラ)
例外: IllegalArgumentException - データまたはハンドラーのいずれかが null の場合。
したがって、Tomcat の実装は、状態がこのコードopen
にあるかどうかを確認するように見えます。
public synchronized void binaryStart() {
checkState(State.OPEN);
state = State.BINARY_FULL_WRITING;
}
そうでない場合はopen
、その例外がスローされます。
Java doc for RemoteEndpoint.Basic
(not RemoteEndpoint.Async
)の下に次のように記載されていることに注意してください。
この RemoteEndpoint の基礎となる Websocket 接続が、別のスレッドを送信するための呼び出しが行われたときに、メッセージの送信でビジーである場合 (たとえば、2 つのスレッドが send メソッドを同時に呼び出そうとした場合、または開発者が途中で新しいメッセージを送信しようとした場合)既存のものを送信すると、接続がすでにビジー状態のときに send メソッドが呼び出され、IllegalStateException がスローされる場合があります。
RemoteEndpoint.Async
!のような段落はありません。
今の質問
RemoteEndpoint.Async.sendBinary
他の何かが同じセッションに書き込んでいる間にセッションを呼び出すことは受け入れられませんか?
受け入れられない場合、リモート エンドポイントに書き込む前にその状態を確認するにはどうすればよいでしょうか。
更新 1:
java.net で同じ問題について議論があったようです。
更新 2:
apache bugzillaの同様のバグ レポートへのリンク。