2

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?

ikolomiets
  • 131
  • 5

0 Answers0