Spring Websocket with SockJs switch from XHR streaming to Websocket - spring

I am using Spring Websocket with SockJs (v1.1.1) over STOMP on client. I create the client with the code below.
SockJS = require('sockjs-client')
Stomp = require('webstomp-client')
stompClient = Stomp.over(new SockJS(url))
It's works fine. But it uses xhr_streaming as transport by default, that is not desirable for me. I want to switch it to websocket tranport.
stompClient = Stomp.over(new SockJS(url, null, {transports:'websocket'}))
But this approach does not work for me. It falls with event:
code: 2000
reason: "All transports failed"
My Spring Websocket configuration is very simple:
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractSessionWebSocketMessageBrokerConfigurer<ExpiringSession> {
#Override
public void configureStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/myEndpoint").setAllowedOrigins("*")
.withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue/", "/topic/");
registry.setApplicationDestinationPrefixes("/app");
}
}
The main problem I face with xhr_streaming is that every stream request updates last access time for user session (I use Spring Session as well). But it's not a desirable behavior for my application. So how I can fix it? And will websocket transport help? Thanks in advance.

So, I've got the reason. I am using a webpack dev server with proxy option. By default it does NOT proxy ws protocol requests (it losts headers). You need toa add ws: true to your config and everything will work fine.
proxy: {
'/api/*': {
target: 'http://localhost:8080',
pathRewrite: {'^/api' : ''},
ws: true
}
}

Related

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

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.

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 websocket (WSS) with angular sockjs (HTTPS) over secure web socket server (tomcat)

I'm working on sending messages from the server side to angular client application using Spring web socket + stomp + SockJsClient at server side and SockJS at the angular side.
My Socket server is a spring boot application and running on 8080 port.
Its working fine over ws/http protocol. but now I have enabled SSL on socket server.
Socket Server configuration.
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/topic");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/sync").setAllowedOrigins("*").withSockJS();
}}
Working code of Java Client over WS
List<Transport> transports = new ArrayList<Transport>(1);
transports.add(new RestTemplateXhrTransport());
SockJsClient sockJsClient = new SockJsClient(transports);
sockJsClient.setMessageCodec(new Jackson2SockJsMessageCodec());
WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
stompClient.setMessageConverter(new StringMessageConverter());
String url = "ws://my-socket.server.com/sync";
StompSessionHandler sessionHandler = new MyStompSessionHandler(senderId, syncUrl, content);
stompClient.connect(url, sessionHandler);
Working code of angular client over HTTP
const Stomp = StompJs.Stomp;
const socket = new SockJS('http://my-socket.server.com/sync');
this.stompClient = Stomp.over(socket);
this.stompClient.connect({}, (res, err) => {}
Now I have implement SSL over my web socket server which is running on separate spring boot server. And update Protocol at server and client side like. ws to wss and http to https.
And also try following things to add SSL Context
StandardWebSocketClient simpleWebSocketClient = new StandardWebSocketClient();
List<Transport> transports = new ArrayList<Transport>(1);
Map<String, Object> userProperties = new HashMap<String, Object>();
userProperties.put("org.apache.tomcat.websocket.SSL_CONTEXT", SSLContext.getDefault());
simpleWebSocketClient.setUserProperties(userProperties);
transports.add(new WebSocketTransport(simpleWebSocketClient));
I have take reference from following stack link but no luck :(
Secure websocket with HTTPS (SSL)
How to use Spring WebSocketClient with SSL?
Please help me to get out of it.
Thank you :)
I also got the same issue , later found I didn't allow end points in security configuration file , just allow the websocket endpoint in antMatchers
WE pass through the same problem, first remove withSockJS like
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfigurer implements WebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/");
config.setApplicationDestinationPrefixes("/js");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/").setAllowedOrigins("*");
}
}
our frontend is in VUE but the connection still the same in JS like.
WEB_SOCKET_URL_PREFIX: 'ws://localhost:8080/'
connect(resolve) {
const URL = '/somePath';
this.webSocket = new WebSocket(HttpConfig.WEB_SOCKET_URL_PREFIX);
this.stompClient = Stomp.over(this.webSocket, { debug: false });
this.stompClient.connect({}, () => {
this.stompClient.subscribe(URL, data => {
console.log(data);
});
});
}
and in your java code you can send the modification with
private final SimpMessagingTemplate simpMessagingTemplate;
public void someMethod(){
...
simpMessagingTemplate.convertAndSend("/somePath", "someContent");
...
}

Unable to connect to websocket on spring AbstractWebSocketMessageBrokerConfigurer

A request to
http://localhost:8080/chat/info
gives
{"entropy":1407128458,"origins":["*:*"],"cookie_needed":true,"websocket":true}
But websocket server is undefined when i try to use it
Using:
Spring Boot
Embedded tomcat
#EnableWebSocketMessageBroker
...
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat").withSockJS();
}
You are enabling SockJS on your server side but using the plain WebSocket API on your client side, use the sockjs client library instead. Replace:
var socket = new WebSocket("ws://localhost:8080/chat");
with:
var socket = new SockJS("http://localhost:8080/chat");

Resources