Почему не работает onmessage при получении ответа с сервера (websocket)?
Написал сервер для работы по ws и пытаюсь проверить его. Конектиться нормально, сообщения отправляются с клиента тоже нормально, но вот метод onmessage не срабатывает при получении сообщения с сервера. В чем проблема не понимаю, нужна помощь.
JS:
var btnSend = document.getElementById('btn_send');
btnSend.addEventListener('click', sendMessage, false);
var btnDisconnect = document.getElementById('btn_disconnect');
btnDisconnect.addEventListener('click', disconnect, false);
let uri = 'ws://localhost:8080/websocket_chat/websocket_chat/Bibus';
var webSocket = new WebSocket(uri);
webSocket.onopen = function(){
console.info('connected with websocket!');
}
webSocket.onmessage = function(event) {
console.info('before parse json in onmessage')
let message = JSON.parse(event.data);
console.info('after parse json in onmessage')
if(message.type == 'MESSAGE') {
updateChatArea(message);
}
}
function updateChatArea(message) {
let from = message.from + "</br>";
let align = "";
let margin = "";
align = "text-align:right";
margin = 'margin:0px 0px 0px 130px;';
let style = 'width:320px;' + margin + align;
let p = document.createElement("p");
p.setAttribute('style', style);
p.innerHTML = from + message.content;
chatArea.appendChild(p);
}
function sendMessage() {
console.info('send message')
let message = {
from : 'Bibus',
type : 'MESSAGE',
content : 'privet'
};
let msgJSON = JSON.stringify(message);
webSocket.send(msgJSON);
}
function disconnect() {
webSocket.close();
console.info('disconnect with websocket!');
}
Java: EndPoint:
@ServerEndpoint(value = "/websocket_chat/{username}",
decoders = WebSocketMessageDecoder.class,
encoders = WebSocketMessageEncoder.class)
class ChatEndpoint {
private Map<Session, String> users = new HashMap<>();
@OnOpen
public void onOpen(Session session, @PathParam("username")String username) throws IOException {
if(!users.containsValue(username)) {
users.put(session, username);
session.getAsyncRemote().sendObject(new WebsocketMessage(MessageType.CONNECTION, true, "Congratulate, good connection!"));
generalSending(new WebsocketMessage(MessageType.USER_LIST, (Set<String>) users.values()));
} else {
session.getAsyncRemote().sendObject(new WebsocketMessage(MessageType.CONNECTION, false, "This username is already exist!"));
}
}
@OnMessage
public void onMessage(Session session, WebsocketMessage message) throws IOException {
generalSending(message);
}
@OnClose
public void onClose(Session session) throws IOException {
users.remove(session);
generalSending(new WebsocketMessage(MessageType.USER_LIST, (Set<String>) users.values()));
}
@OnError
public void onError(Session session, Throwable throwable) {
// Do error handling here
}
private void generalSending(WebsocketMessage message) {
synchronized (users) {
for (Session userSession : users.keySet()) {
userSession.getAsyncRemote().sendObject(message);
}
}
}
}
MessageType:
public enum MessageType {
MESSAGE, USER_LIST, CONNECTION
}
WebsocketMessage:
@Data
public class WebsocketMessage {
private MessageType type;
private String from;
private Set<String> userList;
private String content;
private boolean resultConnectStatus;
public WebsocketMessage(MessageType type, boolean resultConnectStatus, String content) {
this.type = type;
this.content = content;
this.resultConnectStatus = resultConnectStatus;
}
public WebsocketMessage(MessageType type, String from, String content) {
this.type = type;
this.from = from;
this.content = content;
}
public WebsocketMessage(MessageType type, Set<String> userList) {
this.type = type;
this.userList = userList;
}
}
Ответы (2 шт):
но если по-нормальному, то такое сообщение от клиента
let message = {
from : 'Bibus',
type : 'MESSAGE',
content : 'privet'
};
не рационально, from лишнее, т.к. источник определяется однозначно по сессии сообщения, которая однозначно привязывается к регистрации пользователя при его регистрации/авторизации. type - лишнее, потому как всё , что идет от клиента есть "сообщение" , content - лишнее потому, что и так будет понятно...
достаточно разделить сообщение и содержание любым ( к примеру непечатаемым )символом. при коротких сообщениях при наличии from, type, content "кпд" передачи очень маленький.
тип "сообщение" логичнее трактовать как "команда". т.е. команда- (по терминалогии с сервером java - метод) метод, который будет обрабатывать это сообщение. таких "команд" на странице может быть море, и для обработки их можно использовать if или case, можно -но совершенно не нужно, намного эффективнее использовать рефлексию, это будет намного быстрее, компактнее...
проверено, желающие поспорить, узнать подробности - прошу к диалогу.
Спасибо всем кто принимал участие, как многие подметили, да, были проблем на стороне сервера(хотя я усердно не хотел это принимать)). В общем суть проблемы была в том что класс конечной точки был не публичный, в связи с чем выскакивало исключение в логах glasfish (да, я залез туда только сейчас):
[2022-12-07T09:20:58.409-0300] [glassfish 4.0] [INFO] [] [org.glassfish.tyrus.core.AnnotatedEndpoint] [tid: _ThreadID=23 _ThreadName=http-listener-1(5)] [timeMillis: 1670415658409] [levelValue: 800] [[
Exception thrown from onError method 'private void endpoint.ChatEndpoint.onError(javax.websocket.Session,java.lang.Throwable)'
java.lang.IllegalAccessException: Class org.glassfish.tyrus.core.AnnotatedEndpoint can not access a member of class endpoint.ChatEndpoint with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:95)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:261)
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:253)
at java.lang.reflect.Method.invoke(Method.java:594)
at org.glassfish.tyrus.core.AnnotatedEndpoint.callMethod(AnnotatedEndpoint.java:431)
at org.glassfish.tyrus.core.AnnotatedEndpoint.onError(AnnotatedEndpoint.java:455)
at org.glassfish.tyrus.core.AnnotatedEndpoint.callMethod(AnnotatedEndpoint.java:434)
at org.glassfish.tyrus.core.AnnotatedEndpoint.access$100(AnnotatedEndpoint.java:83)
at org.glassfish.tyrus.core.AnnotatedEndpoint$WholeHandler$1.onMessage(AnnotatedEndpoint.java:518)
at org.glassfish.tyrus.core.SessionImpl.notifyMessageHandlers(SessionImpl.java:389)
at org.glassfish.tyrus.core.EndpointWrapper.onMessage(EndpointWrapper.java:495)
at org.glassfish.tyrus.server.TyrusEndpoint.onMessage(TyrusEndpoint.java:174)
at org.glassfish.tyrus.websockets.DefaultWebSocket.onMessage(DefaultWebSocket.java:156)
at org.glassfish.tyrus.websockets.frametypes.TextFrameType.respond(TextFrameType.java:66)
at org.glassfish.tyrus.websockets.DataFrame.respond(DataFrame.java:102)
at org.glassfish.tyrus.servlet.TyrusHttpUpgradeHandler.onDataAvailable(TyrusHttpUpgradeHandler.java:113)
at org.apache.catalina.connector.InputBuffer$ReadHandlerImpl.processDataAvailable(InputBuffer.java:488)
at org.apache.catalina.connector.InputBuffer$ReadHandlerImpl.onDataAvailable(InputBuffer.java:453)
at org.glassfish.grizzly.http.io.InputBuffer.append(InputBuffer.java:855)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:222)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
at java.lang.Thread.run(Thread.java:722)
]]
Ещё раз всем спасибо.
