Java 如何处理websocket@OnError

Java 如何处理websocket@OnError,java,tomcat,websocket,onerror,Java,Tomcat,Websocket,Onerror,除了记录websocket错误外,处理websocket错误的正确方法是什么 关于onError(),端点声明: 开发人员可以在web套接字会话 创建未在web套接字中建模的某种错误 协议例如,这可能是通知传入 消息太大,无法处理,或者传入消息无法处理 被编码 此方法适用于许多类别的异常 (当前)定义为处理: 连接问题,例如,在正式关闭web套接字连接之前发生的套接字故障。这些被建模为SessionException 开发人员创建的消息处理程序调用引发的运行时错误 在调用任何消息处理程序之

除了记录websocket错误外,处理websocket错误的正确方法是什么

关于
onError()
,端点声明:

开发人员可以在web套接字会话 创建未在web套接字中建模的某种错误 协议例如,这可能是通知传入 消息太大,无法处理,或者传入消息无法处理 被编码

此方法适用于许多类别的异常 (当前)定义为处理:

  • 连接问题,例如,在正式关闭web套接字连接之前发生的套接字故障。这些被建模为SessionException

  • 开发人员创建的消息处理程序调用引发的运行时错误

  • 在调用任何消息处理程序之前对传入消息进行编码的转换错误。这些被建模为异常

是否所有这些类型的异常都是致命的,导致websocket关闭

如果发生错误,
onError()
方法是否应该关闭websocket(调用
Session.close()

到目前为止,我认为我有责任彻底结束会话,并将结束原因告知客户。这就是为什么我的
onError()
尝试调用
session.close()
如果
session.isOpen()
返回true,但这导致tomcat(8.0.15)抛出
NullPointerException

...
Caused by: java.lang.NullPointerException
    at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.onWritePossible(WsRemoteEndpointImplServer.java:96)
    at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:81)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:444)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:335)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:264)
    at org.apache.tomcat.websocket.WsSession.sendCloseMessage(WsSession.java:536)
    at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:464)
    at org.apache.tomcat.websocket.WsSession.close(WsSession.java:441)
    at my.package.MyEndpoint.onWebSocketError(MyEndpoint.java:229)
    ... 18 more
这是我的一个误会,还是两者兼而有之

编辑:Java EE websocket示例似乎假设错误是致命的;而且没有必要关闭会话。将记录错误并删除会话:

@OnError
public void error(Session session, Throwable t) {
    /* Remove this connection from the queue */
    queue.remove(session);
    logger.log(Level.INFO, t.toString());
    logger.log(Level.INFO, "Connection error.");
}

@OnError
方法调用并不意味着会话将被关闭;你可以做任何你想做的事,这取决于你的申请所指定的合同

来自tomcat实现的stacktrace看起来像个bug


ad示例-似乎此代码包含其他假设-端点不会引发异常,因此这里捕获的所有内容都来自底层WebSocket框架实现。这并不意味着存在“连接错误”;我可能会立即关闭(如果这是我不希望我的应用程序处理错误的方式);此实现可能会导致打开连接而没有任何消息。

我看到这有点过时,但今天在这里查找此信息时结束。 根据您对websocket状态的依赖程度,您需要手动关闭会话,至少对于javax.websocket实现是这样

在我的例子中,发生的错误导致websession客户端管理实现出现问题,因此我关闭了会话,如上面的示例所示。
我认为这取决于您需要什么,但在这个实现中,它肯定不会进行封闭会话。

谢谢。您确定会话仍处于打开状态吗?这是记录在某个地方吗?好问题-不幸的是,这一信息在任何地方都没有明确说明,但它是有意义的<当会话关闭时,需要调用code>@OnClose(或Endpoint.OnClose),因此在此之前没有必要清理任何与端点相关的资源。另一方面,
@OnError
(或Endpoint.OnError)在端点(+Decode/encodexexeption,…)引发未经处理的异常时随时触发,该异常可以通过端点实现来解决,因此无需关闭底层会话。这对我来说也是有意义的,但我觉得缺少文件是可疑的。这是有意义的,但这并不意味着这就是实际工作的方式我记得曾与JSR356规范负责人讨论过这一点,当时,他确认这是预期行为。无论如何,spec明确提到在会话关闭时必须调用
@OnClose
,因此在那里执行清理不会出错。(您可能需要在
@OnError
中执行其他检查,因为它可以在
@OnClose
之后调用-例如当
@OnClose
引发异常时)。我自己阅读了Undertow(Websockets的JBoss impl)的代码,发现了这种情况
onError
不会隐式调用
onClose
<每当*方法上的其他
引发未经处理的异常时,就会调用code>onError