Unable to connect to websocket on spring AbstractWebSocketMessageBrokerConfigurer - spring

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");

Related

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

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");
...
}

Spring Webflux Netty http and https

I have a requirement where in a Spring Webflux Application I need to listen to HTTP and HTTPS port. I could easily configure HTTPS using
#Bean
public WebServerFactoryCustomizer<NettyReactiveWebServerFactory> customizer() {
return new WebServerFactoryCustomizer<NettyReactiveWebServerFactory>() {
#Override
void customize(NettyReactiveWebServerFactory factory) {
Ssl ssl = new Ssl()
// Your SSL Cusomizations
ssl.setEnabled(true)
ssl.setKeyStore(keystorePath)
ssl.setKeyPassword(keystorePass)
factory.setSsl(ssl)
}
}
}
I am not sure how to add HTTP listener for Netty. For Tomcat Servlet model I have found https://dzone.com/articles/enable-httphttps-spring-boot. Looking a similar setup for Netty Webflux.
This is not supported at the moment. You can watch the following issue in the meantime: https://github.com/spring-projects/spring-boot/issues/12035

Spring Websocket with SockJs switch from XHR streaming to Websocket

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
}
}

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