37

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.

3
  • 14
    Please read 21.4.5 Sending Messages from the Spring Websocket tutorial. This is certainly not how you do it. Also consider reading about Spring scheduling mechanism rather than using raw threads (incorrectly). Commented Jan 31, 2015 at 10:56
  • Thank you for the link, it is exactly what I want to do. About thread I use, obviousely I won't use it in the final state of my application. I have a long process in the server side which will send informations to the client to let him know what steps are already done. Commented Jan 31, 2015 at 15:20
  • Update to the @BoristheSpider's link: 4.4.7. Sending Messages Commented Sep 18, 2021 at 2:06

2 Answers 2

62

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"));
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Which MessageChannel class is being used with the injected SimpMessagingTemplate?
8

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 = 2, timeUnit = TimeUnit.SECONDS)
    public void fireGreeting() {
        this.template.convertAndSend("/topic/greetings", new Greeting("Fire"));
    }
}

And add the @EnableScheduling tag to your Application class.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.