I really like @SubscribeMapping approach to implement RPC-like semantic with STOMP-over-Websocket.
Unfortunately its "magic" requires that annotated method returns a value. But what if return value is not readily available? I want to avoid blocking inside the method waiting for it. Instead I'd like to pass a callback that will publish a value when it's ready. I thought I could use messaging template's convertAndSendToUser() inside a callback to do that. Turns out @SubscribeMapping handling is quite special and is not possible with instance of SimpMessageSendingOperations.
I was able to achieve my goal by calling handleReturnValue() on a SubscriptionMethodReturnValueHandler, but the overall mechanics of this is very tedious if not hackish (like providing dummy instance of MethodParameter to handleReturnValue()):
public class MessageController {
private final SubscriptionMethodReturnValueHandler subscriptionMethodReturnValueHandler;
@Autowired
public MessageController(SimpAnnotationMethodMessageHandler annotationMethodMessageHandler) {
SubscriptionMethodReturnValueHandler subscriptionMethodReturnValueHandler = null;
for (HandlerMethodReturnValueHandler returnValueHandler : annotationMethodMessageHandler.getReturnValueHandlers()) {
if (returnValueHandler instanceof SubscriptionMethodReturnValueHandler) {
subscriptionMethodReturnValueHandler = (SubscriptionMethodReturnValueHandler) returnValueHandler;
break;
}
}
this.subscriptionMethodReturnValueHandler = subscriptionMethodReturnValueHandler;
}
@SubscribeMapping("/greeting/{name}")
public void greet(@DestinationVariable String name, Message<?> message) throws Exception {
subscriptionMethodReturnValueHandler.handleReturnValue("Hello " + name, new MethodParameter(Object.class.getMethods()[0], -1), message);
}
}
So my question is simple: Is there a better way?