I found a lot of tutorials and everything looks right to me, but the client never recieve the response message. The connection is working and the method on the controller is being called, but the subscription by the client looks like its being ignored.
Configuration class:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/topic");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/unify")
.withSockJS();
}
}
Controller class:
@Controller
public class StatusController {
@MessageMapping("/status")
@SendTo("/topic/reply")
public String status(@Payload String test) {
return test;
}
}
Test class:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class WebSocketConnectionTest {
@Value(${local.server.port})
private String port;
@Test
public void testResponse() {
SockJsClient sockJsClient = new SockJsClient(createTransportClient());
WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
boolean exceptionThrowed = false;
final CompletableFuture<String> completableFuture = new CompletableFuture<>();
try {
StompSession session = stompClient.connect("ws://localhost: " + port + "/unify", new StompSessionHandlerAdapter() {}).get(1, TimeUnit.SECONDS);
session.subscribe("/topic/reply", new StompFrameHandler() {
@Override
public Type getPayloadType(StompHeaders headers) {
return String.class;
}
@Override
public void handleFrame(StompHeaders headers, Object payload) {
completableFuture.complete((String)payload);
}
});
session.send("/app/status", "test");
// Always fails
String resp = completableFuture.get(5, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace(); // Always timeout exception
exceptionThrowed = true;
}
Assert.assertFalse(exceptionThrowed);
}
private List<Transport> createTransportClient() {
List<Transport> transports = new ArrayList<>(1);
transports.add(new WebSocketTransport(new StandardWebSocketClient()));
return transports;
}
}
I'm sure that I'm missing something very simple, but I've been trying different configurations for two days without success.
Solution
Looks like the response class needs to have a field "content" of any type and a correspondent getContent() (don't know if the getContent() is really nessessary).