I want to exchange messages by web sockets between 2 java apps.
I have the following server configuration:
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/queue", "/topic");
registry.setUserDestinationPrefix("/user");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
//todo remove handshake handler when authorization is implemented
registry.addEndpoint("/ws").setAllowedOrigins("*").setHandshakeHandler(new TestHandshakeHandler()).withSockJS();
}
}
and inside class marked with #Controller I have wrote following theme:
#MessageMapping("/consumer/client/add")
public void addClientRequest(String msgReq) {
logger.info(msgReq);
}
and inside clien I do connect and in sime bean I wrote following:
#Autowired
private SimpMessagingTemplate simpMessagingTemplate;
...
simpMessagingTemplate.convertAndSend("/app/consumer/client/add", new StubObject("message"));
But after sending from client method addClientRequest doesn't invoke.
Please advice ways to troubleshot this issue.
Actually I don't understand issue. Maybe I send to wrong destination or I have issue with configuration or path is wrong or something else.
P.S.
I know that I can extend StompSessionHandlerAdapter
and obtain session from there but looks like it is the bad style and should be another way to achieve it
P.S.2
Inside class WebSocketTcpConnectionHandlerAdapter(inner class inside WebSocketStompClient) I see private volatile WebSocketSession session;
I want to obtain this object to send messages
I don't think it was designed to be used like this.
I think you must use a specific websocket client. This one for exemple :
http://www.programmingforliving.com/2013/08/jsr-356-java-api-for-websocket-client-api.html
This code :
#MessageMapping("/consumer/client/add")
public void addClientRequest(String msgReq) {
logger.info(msgReq);
}
Will NOT connect to a websocket client and wait to have messages. It expect a client to connect throught it and send messages.
Related
I created a basic web socket with a tutorial.
Here is a configuration:
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat");
registry.addEndpoint("/chat").withSockJS();
}
}
And here is the message handling controller:
#MessageMapping("/chat")
#SendTo("/topic/messages")
public OutputMessage send(Message message) throws Exception {
return new OutputMessage("Hello World!");
}
Everything works, but from my investigation, it looks like the WebSockets by default has an application scope (by connecting to the channel I can see all calls, from all users).
What I want to do is to be able to see only calls from the current user session or current view only.
Any ideas on how to apply these configurations?
I was able to solve this puzzle, so I'm sharing with you my findings.
First, I found information that a simple in-memory message broker can not handle this:
/*
* This enables a simple (in-memory) message broker for our application.
* The `/topic` designates that any destination prefixed with `/topic`
* will be routed back to the client.
* It's important to keep in mind, this will not work with more than one
* application instance, and it does not support all of the features a
* full message broker like RabbitMQ, ActiveMQ, etc... provide.
*/
But this was misleading, as it can be easily achieved by #SendToUser annotation.
Also, the important thing that now on the client-side, you need to add an additional prefix /user/ while subscribing to the channel, so the solution would be:
On the server-side: change #SendTo("/topic/messages") into #SendToUser("/topic/messages").
On the client-side: /topic/messages into the /user/topic/messages.
I have a springboot app and i want to make the websocket connect via devices like phone so i am looking for a way to make my websocket have an entry point that starts with "ws://". When testing my default websocket url which is supposed to be "ws://localhost:8080/websocket-example" on "http://www.websocket.org/echo.html" it does not go through. but the sockjs calls it in my client side using ("http://localhost:8080/websocket-example") which works :
var socket = new SockJS('http://localhost:8080/websocket-example');
stompClient = Stomp.over(socket);
stompClient.connect({},function (frame) {
}
I am presently using stomp on it and my configuration looks like this:
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/websocket-example")
.setHandshakeHandler(new CustomHandshakeHandler()).setAllowedOrigins("*")
.withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic");
registry.setApplicationDestinationPrefixes("/app");
}
}
according to this post it said i could achieve a ws:// entrypoint by removing .withSockJS() which i did, but it still didnt work (on further reading, it was stated that this doesnt work on springboot). The other option was to remove stomp totally, this option works, but then i wouldn't be able to route messages directly to individuals users.
How can i create a ws:// entry point while maintaining stomp on my server side ?
I had a similar problem. Try this, should help.
var socket = new WebSocket('ws://localhost:8080/websocket-example/websocket');
With the example provided by spring.io and http://www.baeldung.com/websockets-spring is helped to create a websocket connection between client and server, but my case is.
- Some one is creating message from UI that is passed to Spring controller (Separate controller).
- From this controller I need to notify/send/broadcast this message to all connected clients.
- How the message is passed to handler from controller where message is received.
I also refereed WebSocket with Sockjs & Spring 4 but without Stomp here and the same question is posted.
Can some one help me here, Thanks in advance !!
I actually write for Baeldung too and am currently writing a small article about how to add security to websockets in Spring! There are just a few steps you need to do to get this all working!
Backend-wise (since you said the UI was already done or being built, I'll just focus on the backend here), it really involves three parts: (1) the necessary POJO's, the controller, and the configuration.
Your POJO's will be very simple - here we just use Greeting and Message which specify a name and basic text data type (I'll skip over this here to save space but you can see it in the resource below).
Your controller will look like this:
#Controller
public class GreetingController {
#MessageMapping("/hello")
#SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
Thread.sleep(1000); // simulated delay
return new Greeting("Hello, " + message.getName() + "!");
}
}
Take a look at the annotations - those are really what set this controller apart from say a normal REST controller.
And your configuration looks like this - again take a look at the annotations - particularly '#EnableWebSocketMessageBroker' - and the class 'AbstractWebSocketMessageBrokerConfigurer':
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/gs-guide-websocket").withSockJS();
}
}
A look at this great resource too: https://spring.io/guides/gs/messaging-stomp-websocket/
My error shows up in the console of my browser:
"WebSocket connection to 'ws://localhost:32768/DspClusterWebServices/myHandler' failed: Unexpected response code: 200"
I am using Spring Websockets 4.1.5 and Tomcat 8.0.18. My WebSocketConfigurer implementation class looks like:
#Configuration
#Controller
#EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer
{
class MyHandler implements WebSocketHandler
{
#Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception
{
System.out.println("afterConntectionEstablished called");
}
...implements rest of functions with a System.out.println and false for supportsPartialMessages()
}
}
#Override registerWebSocketHandlers(WebSocketHandlerRegistry registry)
{
registry.addHandler(myHandler(), "myHandler").withSockJS();
}
#Bean
public WebSocketHandler myHandler()
{
return new MyHandler();
}
}
My testWebsocketClient.js tries to connect with this code, but has a error code of 200:
websocket = new WebSocket("ws://localhost:8080/myApp/myHandler");
I cannot figure out what to try next. I thought that this would cause the afterConnectionEstablished(WebSocketSession session) method to fire? Isn't code 200 good?
Please check http://procbits.com/connecting-to-a-sockjs-server-from-native-html5-websocket!
After you append /websocket (to your URL), it will give you the error
Failed to parse Origin header value [null]
;)
, which then will in turn lead you to that link.
You'll have to add .setAllowedOrigins("*") to your addHandler() method, and then it could finally work!
As my another answer:[https://stackoverflow.com/a/53272666/2930417][1]
I use springboot 2 +STOMP。
remove .withSockJS(),then everything is ok.
I don't know the reason,but works for me.
Have a look at the specification . The server should respond with 101 to signal protocol change from http to ws.
Don't know if this is too late but a solution that I stumbled upon is simply appending the string /websocket after the websocket endpoint that you declared in the spring boot server. This will help keep both the forwarding logic and connect and establish a websocket connection.
For those guys like me who use angular + springboot and got this error. please check if you have enabled the redirect or forward all non api endpoint request back to index.html. like:
#RequestMapping(value = "/**/{[path:[^\\.]*}")
public String redirect() {
// Forward to home page so that route is preserved.
return "forward:/index.html";
}
If you do, disable it and you will get 101
Please check that if 'ws://localhost:32768/DspClusterWebServices/myHandler' is correct.
I have tomcat 8-RC1 installed in order to use javax.websockets to write websocket based applications.
there are examples at http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/ that show exactly the structure of a websocket class so I implemented the following interface:
public interface XpoWebSocket {
#OnOpen
public void onOpen(Session session);
#OnClose
public void onClose();
#OnMessage
public void onTextMessage(String message);
public Session getSession();
}
in the line above the class deceleration I also included the following:
#ServerEndpoint(value = "/ServConnect")
public class ServConnect implements XpoWebSocket {
...
so the ServerEndPoint is to point how to access to websocket, the question is what do i need to set in web.xml ? for now the web socket is still not accessible.
I try to define ServConnect as a regular Servlet in web.xml but that doesn't work. it just time out when I try to access the ServConnect location.
what configuration am I missing to let this ServConnect websocket class work ?
The WebSocket spec says that you have to annotate the concrete class. ServConnect will be treated as a WebSocket endpoint but will not receive any events as the annotations on the interface are ignored.
I'd suggest getting your own version of the Echo example working and then expanding from there.