Python stomp client can not receive any message from Spring 2.x Stomp Service - spring

My spring 1.5 based stomp websocket server and python based stomp client was working fine.
After upgrading spring version to 2.x, the client no longer receives any messages. I have consulted the spring guide but can't find anything wrong.
Python based stomp client:
import stomper
from websocket import create_connection
ws = create_connection('ws://localhost:8080/ws')
ws.send(stomper.subscribe('/msg', 0))
print(ws.recv())
Spring 1.5 based stomp server:
#Configuration
#EnableWebSocketMessageBroker
class DemoConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/msg");
registry.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("ws");
}
}
#Component
#EnableScheduling
class MessageBroker {
#Autowired
private SimpMessagingTemplate messenger;
#Scheduled(fixedRate = 1000)
private void msg() {
messenger.convertAndSend("/msg", "hello");
}
}
Spring 2.x based stomp server(Implement an interface without extending the abstract class):
#Configuration
#EnableWebSocketMessageBroker
class DemoConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/msg");
registry.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("ws");
}
}
#Component
#EnableScheduling
class MessageBroker {
#Autowired
private SimpMessagingTemplate messenger;
#Scheduled(fixedRate = 1000)
private void msg() {
messenger.convertAndSend("/msg", "hello");
}
}

Related

There is an endpoint connection error problem implementing the websocket with spring boot

This is my WebSocketConfig.
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/pub");
registry.enableSimpleBroker("/sub");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/socket").setAllowedOriginPatterns("*").withSockJS();
}
}
This is my SocketController:
#Controller
public class SocketController {
#MessageMapping("/comm/message")
#SendTo("/sub/test")
public Message message(Message message) {
return message;
}
}
I am testing the socket through Chrome's Web Socket Test Client and Advanced Rest Client, but my connection endpoint ws://localhost:8080/socket returns the error.
Is there anything I set wrong?
connecting try tool and endPoint
return message

ServletServerContainerFactoryBean Stomp mode is invalid

The tomcat web container websocket buffer size limit is 8kb, Use ServletServerContainerFactoryBean can be adjusted to 64kb. But it does not support Stomp. I have searched various materials to modify the limit, but all failed. Please give me some guidance, thank you!
#Configuration
public class MyServerContainerConfigurer{
#Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(64*1024);
container.setMaxBinaryMessageBufferSize(64*1024);
return container;
}
}
Effective in normal mode, as shown in the following example.
#Configuration
#EnableWebSocket
public class MyWebSocketConfigurer implements WebSocketConfigurer {
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new TextWebSocketHandler(),"/endpoint").setAllowedOrigins("*");
}
}
It is invalid in Stomp mode, Example of Stomp.
#Configuration
#EnableWebSocketMessageBroker
public class MyWebSocketMessageBrokerConfigurer implements WebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/portfolio").setAllowedOrigins("*");
}
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.setPathMatcher(new AntPathMatcher("."));
config.setApplicationDestinationPrefixes("/app");
config.enableSimpleBroker("/topic", "/queue");
}
#Override
public void configureWebSocketTransport(WebSocketTransportRegistration webSocketTransportRegistration) {
webSocketTransportRegistration
.setMessageSizeLimit(1024 * 1024)
.setSendBufferSizeLimit(1024 * 1024 );
}
}
Error log
2020-06-16 13:45:51.226 DEBUG 11628 --- [nio-8080-exec-4] s.w.s.h.LoggingWebSocketHandlerDecorator : StandardWebSocketSession[id=c11461a9-8340-e006-dda9-cf50716694dd, uri=ws://localhost:8080/portfolio] closed with CloseStatus[code=1009, reason=No async message support and buffer too small. Buffer size: [8,192], Message size: [11,020]]
SpringBoot Version : 2.3.0

Large messages failing on Stomp Controller in Spring Boot

I have a stomp controller in a spring boot application, When ever i send a message which exceeds 256kb it fails to enter the controller. I don't see any error messages. Is there any setting where I can configure it to allow larger messages.
Here is my controller
#Component
#Controller
public class DiscussionController {
#MessageMapping("/discussion")
public void post(DiscussionMessage message) {
}
}
Here is my config file
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer{
private final Logger log = LoggerFactory.getLogger(WebSocketConfig.class);
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("topic");
config.setApplicationDestinationPrefixes("ngdesk");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ngdesk-websocket").setAllowedOrigins("*").withSockJS();
}
}
You need to configure the web-socket transport, e.g.:
#Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setMessageSizeLimit(512 * 1024); // 512K
}

Getting Spring simpMessagingTemplate to work with websocket

I have been trying to get simpMessagingTemplate to send to websocket in Spring but to no avail. From what I can see of related stackoverflow posts and other guides, I have provided the necessary configuration and mapping of paths.
My code is shown as below:
RestController (which I use to invoke sending of the message to the websocket):
#RestController
public class RestControllers {
#Autowired
private SimpMessagingTemplate template;
#RequestMapping("/test")
public String doTest() {
Message m = new Message();
m.setFrom("foo");
m.setText("bar");
template.convertAndSend("/app/chat/test-topic", m);
return m.toString();
}
}
Controller:
#Controller
public class ChatController
{
#MessageMapping("/chat/{topic}")
#SendTo("/topic/messages")
public OutputMessage send(#DestinationVariable("topic") String topic,
Message message) throws Exception
{
System.out.println("THE MESSAGE WAS RECEIVED:" + message.toString());
return new OutputMessage(message.getFrom(), message.getText(), topic);
}
}
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) //?? alternative only?
{
registry.addEndpoint("/chat").setAllowedOrigins("*").withSockJS();
}
}

WebSockets JSR 356 Spring integration #ServerEndpoint

Problem: #Autowired beans in #ServerEndpoint class are null
How can I make sure that this WebSocketController class below will be injected with beans, that is how can I make it managed by Spring? I can connect to the websocket so it works but gameService is always null inside the WebSocketController class instance, so I think that it is created by tomcat somehow and not Spring.
I'm using Spring boot. I just need to figure out how to inject beans into this websocket controller class.
WebSocketController class
#Component
#ServerEndpoint("/sock")
public class WebSocketController {
#Autowired
private GameService gameService;
private static Set<Session> clients = Collections.synchronizedSet(new HashSet<Session>());
#OnMessage
public void handleMessage(Session session, String message) throws IOException {
session.getBasicRemote().sendText(
"Reversed: " + new StringBuilder(message).reverse());
}
#OnOpen
public void onOpen(Session session) {
clients.add(session);
System.out.println("New client #"+session.getId());
if (gameService == null) System.out.println("game service null");
}
#OnClose
public void onClose(Session session) {
clients.remove(session);
System.out.println("Client disconnected #" + session.getId());
}
}
GameService interface and implementation
public interface GameService {
List<Character> getCharacters();
}
#Service
public class GameServiceMockImpl implements GameService {
#Override
public List<Character> getCharacters() {
List<Character> list = new ArrayList<>();
list.add(new Character("aaa","1.png",100));
list.add(new Character("aaa","2.jpg",100));
list.add(new Character("aaa","3.jpg",100));
return list;
}
}
Application class
#SpringBootApplication
public class App {
public static void main(String args[]){
SpringApplication.run(App.class,args);
}
#Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
EDIT:
Using Spring 4 WebSockets doesn't work at all, I can't even connect via a browser.
#Configuration
#EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/myHandler");
}
#Bean
public WebSocketHandler myHandler() {
return new MyHandler();
}
}
public class MyHandler extends TextWebSocketHandler {
#Override
public void handleTextMessage(WebSocketSession session, TextMessage message) {
System.out.println(message.getPayload());
}
}
You are trying to integrate Spring and Java WebSocket API. A class annotated by #Component is registered to a spring bean and its instance is managed by spring but if a class is annotated by #ServerEndpoint it is registered to a server-side WebSocket endpoint and every time the corresponding endpoint's WebSocket is connected to the server, its instance is created and managed by JWA implementation. We you can't use both annotations together.
Either you can use CDI injection(your server should also support)
#ServerEndpoint("/sock")
public class WebSocketController {
#Inject
private GameService gameService;
Or have a look on this doc, Spring 4 has support for WebSocket
Maybe this article can help:
https://spring.io/blog/2013/05/23/spring-framework-4-0-m1-websocket-support
You can use dependency (with spring version > 4)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
And then simply
#ServerEndpoint(value = "/echo", configurator = SpringConfigurator.class)
public class WebSocketEndpoint {
#Inject
private BroadcastService broadcaster;

Resources