Invalid SockJS path /topic/mytopic - required to have 3 path segments - spring-boot

I've got a spring boot app in which I'm adding the websocket feature so that websocket client can make subscription request to subscribe messages off the websocket topic.
In my controller's method, I've added an annotation #SubscribeMapping("/topic/mytopic").
My WebSocketConfig looks like this:
#Configuration
#ComponentScan
#EnableWebSocket
public class WebSocketConfig extends WebSocketMessageBrokerConfiguratioSupport{
#Override
public void registerStompEndpoints(StompEndpointRegistry registry){
registry.addEndpoint("/my-app")
.setAllowedOrigin("*")
.withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry){
registry.enableSimpleBroker("/topic/");
registry.setApplicationDestinationPrefixes("/");
}
}
When I go to the browser and type:
http://localhost:<MY_PORT>/my-app
Then I get a response "Welcome to SockJS!". This indicates that Websocket server is indeed up and running.
But to my surprise, when I'm using my Postman's Websocket feature and trying to do a websocket subscription using the url:
ws://localhost:<MY_PORT>/my-app/topic/mytopic
This error is logged in the console: Invalid SockJS path /topic/mytopic - required to have 3 path segments
and the connection gets disconnected automatically.
Am I doing something wrong here? Please advise.

Related

Postman, Spring boot, WebSocket doesn't send notification

I'm trying send websocket notification to specific endpoint. I created the following configuration
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/my-address");
registry.addEndpoint("/my-address").withSockJS();
}
}
I'm able to connect using postman on address ws://localhost:8080/my-address (session is established). Next I want to send notification to this endpoint within the same application (I'll be generating some messages internally). I use class SimpMessageSendingOperations:
simpMessageSendingOperations.convertAndSend("/my-address", exampleMessage);
None error message is generated and notification does not appear for websocket clients. I also tried
simpMessageSendingOperations.convertAndSend("/topic/my-address", exampleMessage);
and also
simpMessageSendingOperations.convertAndSend("/app/my-address", exampleMessage);
I don't know what I'm doing wrong. Can you help me with this issue?
Thanks in advance for help

websocket spring boot setup

I have a spring boot application. I am trying to add the websocket piece to it. The problem is my angular client can't connect to it. I used smart websocket client google plugin, but still not able to connect. Here is the setup.
I am using Intellij Idea on localhost. the spring boot application is running on localhost:8080. I can see the WebSocketSession is runnign from intellij idea console.
Here is the setup:
#Slf4j
#RestController
public class WebsocketController {
#MessageMapping("/ws-on/hello")
#SendTo("/ws-on/greetings")
public UserStateIndicator greeting(UserStateIndicator indicator) throws Exception {
Thread.sleep(1000); // simulated delay
log.debug("websocket " + indicator.toString());
return indicator;
}
}
#Configuration
#EnableWebSocketMessageBroker
public class WebsocketConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/ws-on");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws-on")
.setAllowedOrigins("http://localhost:4200")
.withSockJS();
}
}
my angular is running on localhost:4200.
I used ws://localhost:8080/ws-on as the url from StompJS to connect.
My question is how do I find the websocket url to connect, and how do I know the websocket is running on the spring boot server?
finally I figured it out. Because I am using SockJS on both angular and spring boot, so, the URL is actaully http not ws. the correct url to connect is then http://localost:8080/ws-on

stomp_dart_client not connecting to server

Trying to set connection to my spring boot server in flutter app
final socketUrl = 'https://10.0.0.6:8443/notifications';
if (stompClient == null) {
stompClient = StompClient(
config: StompConfig.SockJS(
url: socketUrl,
onConnect: onConnect,
onWebSocketError: (dynamic error) => print(error.toString()),
));
print(stompClient.config.url);
stompClient.activate();
}
but function onConnect is never called and i dont get any error message neither. I have tried change url to wss://10.0.0.6:8443/notifications and remove SockJs with same result. Also tried to connect to wss://echo.websocket.org without any success.
Web server is config as follow and it has valid certs
#Configuration
#EnableWebSocketMessageBroker
public class webSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/notification/item");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/notifications");
registry.addEndpoint("/notifications").withSockJS();
}
}
Calling socket from JS web app on same server is working fine.
I have tried other flutter libs (Stomp, Socket_IO, WebSocketChannel) to connect but without any success. Is there something I am missing in configuration ?
You are probably running into problems with CORS. Please try only this line:
registry.addEndpoint("/notifications").setAllowedOrigins("*").withSockJS();
while keeping the client as it is posted here.

Spring Boot WebSockets notifications

In my Spring Boot application I'm trying to implement a notifications functionality based on WebSockets.
I have provided a following configuration:
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/notifications").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic", "/queue");
}
}
and trying to use SimpMessagingTemplate in order to send a message from server side to a specific client(user).
#Autowired
private SimpMessagingTemplate simpMessagingTemplate;
public void sendMessages() {
simpMessagingTemplate.convertAndSendToUser(%user%, "/horray", "Hello, World!");
}
Right now I don't understand a few things:
What value should be used for %user% parameter of
simpMessagingTemplate.convertAndSendToUser method ?
What is the correlation between my /notifications endpoint
registered in WebSocketConfig.registerStompEndpoints method and
destination parameter of
simpMessagingTemplate.convertAndSendToUser method and how to properly use it?
How to protect the users from reading other people's messages on the
client ?
The user parameter is the name that the client use when he subscribes the destination, see Spring Reference Chapter 26.4.11 User Destinations
Destination vs Endpoint:
Endpoint is the url where the websocket/message brocker is listening
Destination is the topic or subject within the message brocker

How to Create Spring WebSocket Application With HTML5 WebSocket API?

Recent Version of Spring WebSocket works with SockJS and StompJS libraries. But i don't like to use theme in my application. So how to create Spring WebSocket application with HTML5 WebSocket API and integrate our application with Spring Security?
I could not find any good example on how to configure spring websocket without sockjs but i found some helpful documentation in spring documentation site and i like to share that. Well, How to Create Spring WebSocket Application With HTML5 WebSocket API?
First: Create a Class that extends TextWebSocketHandler or BinaryWebSocketHandler and Annotate it with #Component annotation and Override its appropriate method.This Class works like handler methods in controllers.
#Component
public class SimpleWebSocketHandler extends TextWebSocketHandler {
#Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
// Sends back response to client.
session.sendMessage(new TextMessage("Connection is all right."));
}
}
Second: Create a Configuration Class that implements WebSocketConfigurer and Annotate it with #Configuration and #EnableWebSocket annoations and Override its appropriate method.This Class uses Handler Class that we created already.
#Configuration
#EnableWebSocket
public class WebSocketConfigurations implements WebSocketConfigurer {
#Autowired
private SimpleWebSocketHandler simpleWebSocketHandler;
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// Regsiters a handler for related endpoint.
registry.addHandler(simpleWebSocketHandler, "/chat");
}
}
Third: Add all your WebSokcet Endpoints to your Spring Security Configuration.
httpSecurity.authorizeRequests()
.antMatchers("/chat").permitAll();
Fourth: We create a new javascript WebSocket objet with appropriate URL.
// Create WebSocket Object.
var ws = new WebSocket("ws://localhost:8080/chat");
// Runs when connecion is estabilished.
ws.onopen = function () {
// Sends request to server with string value.
ws.send("webSocket");
};
// Runs when response is ready.
// Use event to get response value.
ws.onmessage = function (event) {
};
Note: WebSocket URLs Format: ws://domain:port/endpoint

Resources