Spring WebSocket @SendToSession: отправлять сообщения в определенный сеанс

Можно ли отправить сообщение на конкретный сеанс?

У меня есть неопознанная веб-розетка между клиентами и сервлетом Spring. Мне нужно отправить нежелательное сообщение определенному соединению, когда асинхронное задание заканчивается.

@Controller
public class WebsocketTest {


     @Autowired
    public SimpMessageSendingOperations messagingTemplate;

    ExecutorService executor = Executors.newSingleThreadExecutor();

    @MessageMapping("/start")
    public void start(SimpMessageHeaderAccessor accessor) throws Exception {
        String applicantId=accessor.getSessionId();        
        executor.submit(() -> {
            //... slow job
            jobEnd(applicantId);
        });
    }

    public void jobEnd(String sessionId){
        messagingTemplate.convertAndSend("/queue/jobend"); //how to send only to that session?
    }
}

Как видно из этого кода, клиент может запустить асинхронное задание, а когда оно завершится, ему нужно сообщение о завершении. Очевидно, мне нужно сообщать только заявителю, а не вещать всем. Было бы здорово иметь@SendToSession аннотация илиmessagingTemplate.convertAndSendToSession метод.

ОБНОВИТЬ

Я попробовал это:

messagingTemplate.convertAndSend("/queue/jobend", true, Collections.singletonMap(SimpMessageHeaderAccessor.SESSION_ID_HEADER, sessionId));

Но это транслирует все сеансы, а не только указанный.

ОБНОВЛЕНИЕ 2

Протестируйте с помощью метода convertAndSendToUser (). Этот тест и взломать официальный учебник Spring:https://spring.io/guides/gs/messaging-stomp-websocket/

Это код сервера:

@Controller
public class WebsocketTest {

    @PostConstruct
    public void init(){
        ScheduledExecutorService statusTimerExecutor=Executors.newSingleThreadScheduledExecutor();
        statusTimerExecutor.scheduleAtFixedRate(new Runnable() {                
            @Override
            public void run() {
                messagingTemplate.convertAndSendToUser("1","/queue/test", new Return("test"));
            }
        }, 5000,5000, TimeUnit.MILLISECONDS);
    } 

     @Autowired
        public SimpMessageSendingOperations messagingTemplate;
}

и это код клиента:

function connect() {
            var socket = new WebSocket('ws://localhost:8080/hello');
            stompClient = Stomp.over(socket);
            stompClient.connect({}, function(frame) {
                setConnected(true);
                console.log('Connected: ' + frame);
                stompClient.subscribe('/user/queue/test', function(greeting){
                    console.log(JSON.parse(greeting.body));
                });
            });
        }

К сожалению, клиент не получает ответ за сеанс каждые 5000 мс, как ожидалось. Я уверен, что "1" является допустимым ID сессии для второго подключенного клиента, потому что я вижу его в режиме отладки сSimpMessageHeaderAccessor.getSessionId()

ФОНОВЫЙ СЦЕНАРИЙ

Я хочу создать индикатор выполнения для удаленного задания, клиент запрашивает у сервера асинхронное задание и проверяет его выполнение с помощью сообщения websocket, отправленного с сервера. Это НЕ загрузка файла, а удаленное вычисление, поэтому только сервер знает ход выполнения каждого задания. Мне нужно отправить сообщение на конкретную сессию, потому что каждая работа запускается сессией. Клиент запрашивает удаленное вычисление. Сервер запускает это задание и на каждом шаге задания отвечает клиенту-заявителю с его статусом выполнения задания. Клиент получает сообщения о своей работе и создает строку прогресса / состояния. Вот почему мне нужны сообщения для каждой сессии. Я также мог бы использовать сообщения для каждого пользователя, но Springне обеспечивает на пользователя нежелательных сообщений. (Не удается отправить сообщение пользователя с помощью Spring Websocket)

РАБОЧЕЕ РЕШЕНИЕ

 __      __ ___   ___  _  __ ___  _  _   ___      ___   ___   _    _   _  _____  ___  ___   _  _ 
 \ \    / // _ \ | _ \| |/ /|_ _|| \| | / __|    / __| / _ \ | |  | | | ||_   _||_ _|/ _ \ | \| |
  \ \/\/ /| (_) ||   /| ' <  | | | .` || (_ |    \__ \| (_) || |__| |_| |  | |   | || (_) || .` |
   \_/\_/  \___/ |_|_\|_|\_\|___||_|\_| \___|    |___/ \___/ |____|\___/   |_|  |___|\___/ |_|\_|

Начиная с решения UPDATE2, мне пришлось завершить метод convertAndSendToUser последним параметром (MessageHeaders):

messagingTemplate.convertAndSendToUser("1","/queue/test", new Return("test"), createHeaders("1"));

гдеcreateHeaders()&nbsp;этот метод:

private MessageHeaders createHeaders(String sessionId) {
        SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
        headerAccessor.setSessionId(sessionId);
        headerAccessor.setLeaveMutable(true);
        return headerAccessor.getMessageHeaders();
    }