Reputation: 81
I am trying to use websocket over spring to send and receive some strings. I used to work with an example over google but after putting all together i receive a request to an url that is not available on my contorller request.
flow/websocket/add/info?t=1540813753999
My controller look like this :
@Controller("webSocketController") @RequestMapping("/websocket")
public class WebSocketController {
@MessageMapping("/add" )
@SendTo("/topic/showResult")
public Result addNum(CalcInput input) throws Exception {
Thread.sleep(2000);
Result result = new Result(input.getNum1()+"+"+input.getNum2()+"="+(input.getNum1()+input.getNum2()));
return result;
}
@RequestMapping("/start")
public String start() {
return "start";
} }
and
@Configuration
@EnableWebSocketMessageBroker
public class AppWebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/calcApp");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/add").setAllowedOrigins("*").withSockJS();
}
}
Javascript part :
<s:url value="/flow/websocket/add" var="sockendpoint" htmlEscape="true" />
<s:url value="/flow/websocket/topic/showResult" var="showresult" htmlEscape="true" />
<s:url value="/flow/websocket/calcApp/add" var="calcApp" htmlEscape="true" />
<script type="text/javascript">
var stompClient = null;
function setConnected(connected) {
document.getElementById('connect').disabled = connected;
document.getElementById('disconnect').disabled = !connected;
document.getElementById('calculationDiv').style.visibility = connected ? 'visible'
: 'hidden';
document.getElementById('calResponse').innerHTML = '';
}
function connect() {
var socket = new SockJS('${sockendpoint}');
//var socket = new WebSocket('${sockendpoint}');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('${showresult}', function(calResult) {
showResult(JSON.parse(calResult.body).result);
});
}, function(error) {
console.log(error);
});
}
function disconnect() {
stompClient.disconnect();
setConnected(false);
console.log("Disconnected");
}
function sendNum() {
var num1 = document.getElementById('num1').value;
var num2 = document.getElementById('num2').value;
stompClient.send("${calcApp}", {}, JSON.stringify({
'num1' : num1,
'num2' : num2
}));
}
function showResult(message) {
var response = document.getElementById('calResponse');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.appendChild(document.createTextNode(message));
response.appendChild(p);
}
</script>
/flow is the main mapping for spring on dispatcher
Thank you in advance
Upvotes: 2
Views: 3049
Reputation: 432
It's because of the issue of /info=34424 - with 404 error - that I had to abandon it. I have Spring 4.2 in my project and many SockJS Stomp implementations usually work well with Spring Boot implementations. This implementation from Baeldung worked(for me without changing from Spring 4.2 to 5). After Using the dependencies mentioned in his blog, it still gave me ClassNotFoundError. I added the below dependency to fix it.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.3.RELEASE</version>
</dependency>
Baeldung's implementation curiously does not make any such calls
flow/websocket/add/info?t=1540813753999
What it does (on send and receive) is below. I am only pasting it in case people well-versed with these libraries can further add insights on this forum.
>>> SEND
destination:/app/chat
content-length:38
{"from":"nicholas","text":"try again"}
<<< MESSAGE
destination:/topic/messages
content-type:application/json;charset=UTF-8
subscription:sub-0
message-id:m3p096zk-11
content-length:53
{"from":"nicholas","text":"try again","time":"13:46"}
Upvotes: 0
Reputation: 793
The "info" endpoint is added automatically by SockJS as it is part of its protocol.
This is completely normal and the endpoint is used by the client to retrieve information about the server features.
Also, AFAIK you cannot avoid it since it is specified as part of the protocol thus mandatory.
Please refer to the Spring documentation. Link below:
Section 22.3.1 Overview of SockJS, which explains the reason behind the endpoint.
EDIT: The real problem wasn't related with the "info" endpoint which is added automatically by the framework.
The issue is that the client was calling the STOMP server endpoint at servlet/app/stompEndpoint in the following line:
<s:url value="/flow/websocket/add" var="sockendpoint" htmlEscape="true" />
The stomp server endpoint /add is not part of the App itself since a server can contain in fact multiple Apps. So, the correct path should be servlet/stompEndpoint.
<s:url value="/flow/add" var="sockendpoint" htmlEscape="true" />
Also, you can check the following Hello World example, which explains this in a more detailed way: https://spring.io/guides/gs/messaging-stomp-websocket/
Upvotes: 2