Spring WebSockets Stomp.subscribe not working - javascript

I've been trying to implement a basic Spring WebSockets application following the official Spring guide. The files I have are the following:
WebSocketConfig.java
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/chat");
registry.setApplicationDestinationPrefixes("/message");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/ws-connect").setAllowedOrigins("*").withSockJS();
}
}
MessageController.java
#Controller
public class MessageController {
#MessageMapping(value = "/test")
#SendTo("/private")
public Message message(String messageText) {
Message message = new Message();
message.setMessage(messageText);r);
message.setTimestamp(new Date());
return message;
}
}
sockets.js
var stompClient = null;
function connect() {
var socket = new SockJS('http://localhost:8080/ws-connect');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
console.log('Connected: ' + frame);
stompClient.subscribe('/chat/private', function(message) {
console.log('Here');
console.log('Message is: ' + message);
});
console.log('Here2');
})
}
connect();
function sendMessage() {
stompClient.send('/message/test', {}, "Hello self!");;
}
I have a button in my index.html that when clicked calls the sendMessage function and I get a console log that the message has been sent, however I never get the reply in the subscribe function. The client successfully connects to the WebSocket server and I get this outputted in the console. What am I doing wrong?

Change /private to /chat/private
Change it like below :
#Controller
public class MessageController {
#MessageMapping(value = "/test")
#SendTo("/chat/private")
public Message message(String messageText) {
Message message = new Message();
message.setMessage(messageText);
message.setTimestamp(new Date());
return message;
}
}

Related

Can't connect client (Javascript) to existing socket server

I have an existing socket server that listens on port 6868. It is written in Java.
I need to connect a client to the server. The client is coded in Javascript in my React app.
I have tried just about every possible combination of tutorials I have found on the internet but I still can't get the client to connect.
import * as io from "socket.io-client";
export default () => {
// eslint-disable-next-line no-restricted-globals
self.onmessage = (message) => {
const data = message.data;
try {
var socket = io("http://localhost:6868/");
} catch (error) {
console.log("do nothing: " + error);
}
};
};
No matter what, I get the same error: ReferenceError: socket_io_client__WEBPACK_IMPORTED_MODULE_0___default is not defined.
This is the version I am using as seen in package.json: "socket.io-client": "^4.4.0"
I installed it with this command: npm i socket.io-client
Turns out that socket.io can't be used to connect to the ServerSocket that I have in Java. To fix this, I changed ServerSocket to be a WebSocketServer.
Here is all of the code needed to make Java WebSocket connect with JavaScript client:
WebsocketServer.java
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import java.net.InetSocketAddress;
import java.util.HashSet;
import java.util.Set;
public class WebsocketServer extends WebSocketServer {
private static int TCP_PORT = 6868;
private static Set<WebSocket> conns;
public WebsocketServer() {
super(new InetSocketAddress(TCP_PORT));
conns = new HashSet<>();
}
#Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
conns.add(conn);
conn.send("hello!!");
System.out.println("New connection from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
#Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
conns.remove(conn);
System.out.println("Closed connection to " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
#Override
public void onMessage(WebSocket conn, String message) {
System.out.println("Message from client: " + message);
for (WebSocket sock : conns) {
sock.send("SENDING BACK" + message);
}
}
#Override
public void onError(WebSocket conn, Exception ex) {
//ex.printStackTrace();
if (conn != null) {
conns.remove(conn);
// do some thing if required
}
System.out.println("ERROR from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
public static Set<WebSocket> getConns() {
return conns;
}
}
And launch the server from main() with new WebsocketServer().start();
client.js
var connection = new WebSocket("ws://127.0.0.1:6868");
connection.onopen = function () {
console.log("Connected!");
connection.send("Ping"); // Send the message 'Ping' to the server
};
// Log errors
connection.onerror = function (error) {
console.log("WebSocket Error " + error);
};
// Log messages from the server
connection.onmessage = function (e) {
console.log("Server: " + e.data);
};
And the dependency for the Java Web Socket:
<dependency>
<groupId>
org.java-websocket
</groupId>
<artifactId>
Java-WebSocket
</artifactId>
<version>
1.3.0
</version>
</dependency>

SignalR client side method not firing on from server side button click

I am having a Visual Studio 2019 based SignalR Application, where client connects to server.
Following javascript function is called when a page is loaded and it connects to a running server with a successful connectionid.
function Connect() {
$.connection.hub.url = url;
stockTickerHubProxy = $.connection.mobileStockTickerHub;
if (stockTickerHubProxy) {
$.connection.hub.start().done(function () {
console.log("Connected...");
connectionId = $.connection.hub.id;
console.log(connectionId)
stockTickerHubProxy.server.setUserName(code);
})
.fail(function () {
alert("Can't connect");
})
;
stockTickerHubProxy.client.addMessage = function (name, message) {
console.log(name + ":" + message);
}
stockTickerHubProxy.client.showtradenotification = function (msg) {
alert(msg)
}
$.connection.hub.disconnected(function () {
console.log("Server disconnected.");
});
$.connection.hub.reconnecting(function () {
console.log("Server reconnecting...");
});
$.connection.hub.reconnected(function () {
console.log("Server reconnected...");
Connect();
});
$.connection.hub.error(function (error) {
console.log('SignalR error: ' + error)
});
}
}
On server, I am executing following test code for checking the function running in javascript html page. Following is the code.
private async void button1_ClickAsync(object sender, EventArgs e)
{
mhubContext = GlobalHost.ConnectionManager.GetHubContext<MobileStockTickerHub>();
await mhubContext.Clients.All.showtradenotification("Hello");
}
Following is the hub class MobileStockTickerHub
public class MobileStockTickerHub : Hub
{
//Called when a client is connected
public override Task OnConnected()
{
_users.TryAdd(Context.ConnectionId, Context.ConnectionId);
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
string username;
_users.TryRemove(Context.ConnectionId, out username);
return base.OnDisconnected(stopCalled);
}
public override Task OnReconnected()
{
_users.TryAdd(Context.ConnectionId, Context.ConnectionId);
return base.OnReconnected();
}
public string SetUserName(string userName)
{
_users[Context.ConnectionId] = userName;
return "Received ping from " + userName;
}
}
Again, when button1_ClickAsync is fired, there is no activity on the webpage, that should fire showtradenotification with an alert message.
Let me know where I am wrong.
Thanks.
Move your client function before your hub.start. You should always register at least one function before your start. See the note regarding in the docs.

WebSocket stomp client subscribe for some devices are not working

I am trying to implement a spring boot chat application using WebSocket stomp client. If I send messages from one device to 4,5 devices then some are getting the messages and some are not. Some can send messages but don't receive any message and some are working completely fine. My application is running on wildfly server and the URL is over https.
Here is my js file. From my JSP page I am calling sendMsg with all parameter and through render method I am attaching the response with JSP using Handlebars.
if (!window.location.origin) {
window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
}
const url = window.location.origin+contextPath;
let stompClient;
let selectedUser;
let newMessages = new Map();
function connectToChat(userName, topicName) {
console.log("connecting to chat...")
let socket = new SockJS(url + '/chat');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
console.log("connected to: " + frame);
stompClient.subscribe("/topic/decision-log", function (response) {
let data = JSON.parse(response.body);
var msg = data.message;
var fromlogin = data.message;
render(data.username, msg, fromlogin);
});
});
}
connectToChat("1", "decision-log");
function sendMsg(from, text, username) {
stompClient.send("/app/chat/" + from, {}, JSON.stringify({
fromLogin: from,
message: text,
topicName: topicName,
username: username
}));
}
function render(username, message, projectId) {
var templateResponse = Handlebars.compile($("#message-response-template").html());
var contextResponse = {
username: username,
response: message,
date: date,
projectId: projectId
};
setTimeout(function () {
$chatHistoryList.append(templateResponse(contextResponse));
scrollToBottom();
}.bind(this), 1500);
}
Here is my WebSocket configuration file:
#Configuration
#EnableWebSocketMessageBroker
public class WebsocketConfiguration implements WebSocketMessageBrokerConfigurer{
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat").setAllowedOrigins("*").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app").enableSimpleBroker("/topic");
}
}
This is the controller. I always save all messages on the database that are coming through WebSocket that's why I can be sure that all devices can send messages as they have been saved on the database.
#Controller
#AllArgsConstructor
public class MessageController {
#Autowired
private SimpMessagingTemplate simpMessagingTemplate;
private final DecisionLogService decisionLogService;
#MessageMapping("/chat/{to}")
public void sendMessage(#DestinationVariable String to, MessageModel message, Authentication authentication ) {
simpMessagingTemplate.convertAndSend("/topic/decision-log", message);
AuthResponse userDetails = (AuthResponse) authentication.getDetails();
DecisionLogCreateRequest decisionLogCreateRequest = new DecisionLogCreateRequest();
decisionLogCreateRequest.setDecision(message.getMessage());
decisionLogCreateRequest.setProjectId(to);
ServiceResponseExtended<Boolean> response = decisionLogService.addDecisionLog(userDetails.getAccessToken(), decisionLogCreateRequest);
}
}
I can not find anything similar this issue. Please help me with right information and suggestion, and if anyone faced same kind of problem please share with me.
The problem was solved after configuring RabbitMQ Stomp Broker as a message broker instead of SimpleBroker.
Current WebSocket configuration:
#Configuration
#EnableWebSocketMessageBroker
public class WebsocketConfiguration implements WebSocketMessageBrokerConfigurer{
#Value("${stomp-broker-relay-host}")
private String RELAY_HOST;
#Value("${stomp-broker-relay-port}")
private String RELAY_PORT;
#Value("${stomp-broker-login-user}")
private String USER;
#Value("${stomp-broker-login-pass}")
private String PASS;
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat").setAllowedOrigins("*").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableStompBrokerRelay("/topic").setRelayHost(RELAY_HOST).setRelayPort(Integer.parseInt(RELAY_PORT)).setClientLogin(USER)
.setClientPasscode(PASS);
}
}
Reference:
https://medium.com/#rameez.s.shaikh/build-a-chat-application-using-spring-boot-websocket-rabbitmq-2b82c142f85a
https://www.javainuse.com/misc/rabbitmq-hello-world

Getting 404 in WebSocket connection

I have a backend java code for websocket.
SessionEndpoint:
#ServerEndpoint("/session")
public class SessionEndpoint {
private static Set<SessionEndpoint> sessionEndpoints = new CopyOnWriteArraySet<>();
#OnMessage
public void onMessage(Session session, String sessionId) {
Map<String, Object> attributes = new HashMap<>();
attributes.put("sessionId", sessionId);
sessionEndpoints.forEach(endpoint -> {
synchronized (endpoint) {
try {
session.getBasicRemote().sendObject(attributes);
} catch (IOException | EncodeException e) {
e.printStackTrace();
}
}
});
}
}
Trying to connect to websocket from javascript, code is given below.
let webSocket = new WebSocket('ws://localhost:9999/session');
webSocket.onopen = () => webSocket.send('hello');
webSocket.onmessage = function(response) {
console.log(response);
};
I get 404 response code while connecting to websocket. How should I connect to webscoket from javascript ?

pass data between browser and java SE project using websocket

I created a sample project using Java and JavaScript. Java is used to create the server part and JavaScript is used for client part. I have used jetty version 9.0.5 to develop javaSE project.
This is my server part:
package com.websocet;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.websocket.server.WebSocketHandler;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
public class WebSocketTest {
public static void main(String[] args) throws Exception {
try{
Server server = new Server(8080);
WebSocketHandler wsHandler = new WebSocketHandler() {
#Override
public void configure(WebSocketServletFactory factory) {
factory.register(MyWebSocketHandler.class);
}
};
server.setHandler(wsHandler);
server.start();
server.join();
}catch(Exception e){
System.out.println("Error "+ e);
}
}
}
This my MyWebSocketHandler class
package com.websocet;
import java.io.IOException;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
public class MyWebSocketHandler {
#OnWebSocketClose
public void onClose(int statusCode, String reason) {
System.out.println("Close: statusCode=" + statusCode + ", reason=" + reason);
}
#OnWebSocketError
public void onError(Throwable t) {
System.out.println("Error: " + t.getMessage());
}
#OnWebSocketConnect
public void onConnect(Session session) {
System.out.println("Connect: " + session.getRemoteAddress().getAddress());
try {
session.getRemote().sendString("Hello Webbrowser");
} catch (IOException e) {
System.out.println("Error -----" + e);
e.printStackTrace();
}
}
#OnWebSocketMessage
public void onMessage(String message) {
System.out.println("Message: " + message);
}
}
This is my client part:
console.log("start index.js");
var ws = new WebSocket("ws://localhost:8080/");
ws.onopen = function() {
console.log("Opened!");
ws.send("Hello Server");
};
ws.onmessage = function (evt) {
console.log("Message: " + evt.data);
};
ws.onclose = function() {
console.log("connection Closed...");
};
ws.onerror = function(err) {
console.log("Error"+ err);
};
when I run the server part it works well.
2015-12-11 12:02:31.081:INFO:oejs.Server:main: jetty-9.0.5.v20130815
2015-12-11 12:02:31.141:INFO:oejs.ServerConnector:main: Started ServerConnector#470e2030{HTTP/1.1}{0.0.0.0:8080}
But after I run client part, the server throws below exception.
2015-12-11 12:02:42.055:WARN:oejs.HttpChannel:qtp769287236-18: /
org.eclipse.jetty.websocket.api.InvalidWebSocketException: com.websocet.MyWebSocketHandler does not implement org.eclipse.jetty.websocket.api.WebSocketListener or declare #WebSocket
at org.eclipse.jetty.websocket.common.events.EventDriverFactory.wrap(EventDriverFactory.java:385)
at org.eclipse.jetty.websocket.server.WebSocketServerFactory.acceptWebSocket(WebSocketServerFactory.java:177)
at org.eclipse.jetty.websocket.server.WebSocketHandler.handle(WebSocketHandler.java:90)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:445)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:268)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:229)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.run(AbstractConnection.java:358)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:601)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:532)
at java.lang.Thread.run(Thread.java:745)
I downloaded jetty-distribution-9.0.5.v20130815 and added it in to eclipse IDE.
I am new to web socket. So please help me to resolve this problem. My goal is getting data from my web browser and passing it into my JavaSE project. If anyone knows to do this please let me know.
I found the answer to my question. I had missed an annotation. It has to be corrected as #WebSocket
#WebSocket
public class MyWebSocketHandler {
......
}

Categories

Resources