Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send message to client through websocket using Spring

I try to use Spring with websocket. I started my investigation with this tutorial.

In my side client I have something like that to initialize the connection to the server :

function connect() {
    var socket = new SockJS('/myphotos/form');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function(frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function(greeting){
            showGreeting(JSON.parse(greeting.body).content);
        });
    });
}

It works great, in my controller I’m able to do my process in the following class :

@Controller
@RequestMapping("/")
public class PhotoController {

    @MessageMapping("/form")
    @SendTo("/topic/greetings")
    public Greeting validate(AddPhotosForm addPhotosForm) {
        return new Greeting("Hello world !");
    }
}

Now what I want to do it’s having a thread sending a message to the client listening on “/topic/greeting”. I wrote my Runnable class like this :

public class FireGreeting implements Runnable {

    private PhotoController listener;

    public FireGreeting(PhotoController listener) {
        this.listener = listener;
    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep( 2000 );
                listener.fireGreeting();
            } catch ( InterruptedException e ) {
                e.printStackTrace();
            }
        }   
    }
}

And completed my controller like that :

@Controller
@RequestMapping("/")
public class PhotoController {

    @MessageMapping("/form")
    @SendTo("/topic/greetings")
    public Greeting validate(AddPhotosForm addPhotosForm) {

        // added this part
        FireGreeting r = new FireGreeting( this );
        new Thread(r).start();

        return new Greeting("Hello world !");
    }

    // added this method
    @SendTo("/topic/greetings")
    public Greeting fireGreeting() {
        System.out.println("Fire");
        return new Greeting("Fire");
    }
}

The method PhotoController.fireGreeting is called as I want but nothing happened on the client side. Any suggestions ? Thank you.

like image 409
cheb1k4 Avatar asked Jan 31 '15 10:01

cheb1k4


People also ask

Can a WebSocket server send message to client?

The Message event takes place usually when the server sends some data. Messages sent by the server to the client can include plain text messages, binary data, or images. Whenever data is sent, the onmessage function is fired.

How do I send a WebSocket message?

To send a message through the WebSocket connection you call the send() method on your WebSocket instance; passing in the data you want to transfer. socket. send(data); You can send both text and binary data through a WebSocket.

Does spring boot support WebSocket?

Spring Boot includes the spring-WebSocket module, which is compatible with the Java WebSocket API standard (JSR-356). Implementing the WebSocket server-side with Spring Boot is not a very complex task and includes only a couple of steps, which we will walk through one by one.


2 Answers

I was able to solve my problem thanks to @Boris the Spider. The correct solution is to do something like that :

@Controller @RequestMapping("/") public class PhotoController {      @Autowired     private SimpMessagingTemplate template;      @MessageMapping("/form")     @SendTo("/topic/greetings")     public Greeting validate(AddPhotosForm addPhotosForm) {          FireGreeting r = new FireGreeting( this );         new Thread(r).start();          return new Greeting("Hello world !");     }      public void fireGreeting() {         System.out.println("Fire");         this.template.convertAndSend("/topic/greetings", new Greeting("Fire"));     } } 
like image 181
cheb1k4 Avatar answered Sep 26 '22 08:09

cheb1k4


A better way to schedule periodic tasks is, as suggested by @Boris the Spider, to use Spring scheduling mechanisms (see this guide).

For the sake of Separation of Concerns, I would also separate scheduled-related code from controller code.

In your case you could use a class like this one:

@Component public class ScheduledTasks {      @Autowired     private SimpMessagingTemplate template;      @Scheduled(fixedRate = 2000)     public void fireGreeting() {         this.template.convertAndSend("/topic/greetings", new Greeting("Fire"));     } } 

And add the @EnableScheduling tag to your Application class.

like image 29
mfilippo Avatar answered Sep 25 '22 08:09

mfilippo