12

I need to implement RPC over STOMP, where the client runs with javascript in a browser, and the server side is implemented using Spring messaging capabilities.

While using @MessageMapping is fine for normal messaging, I find using @SendToUser quite limitating for implementing RPC because the client has an hard time to understand which reply is associated with which request in a scenario when multiple simultaneous requests are being made from the client.

Of course there is no problem when just only one request is made, and the client waits for its reply, but problems arise when the client has to keep track of multiple "open" rpc calls.

I've managed to make the system mostly fine by associating an ID with every request, i.e.: the client sends an id together with the message, and the server replies with a special message wrapper that contains this id, so the client is able to associate asynchronous replies with requests.

This works fine but has several limitations:

  • I have to develop code that needs to understand this structure, and that defies the uitlity to have simple annotated methods

  • when the server side code generates an Exception the Spring @MessageExceptionHandler get called and the correct Exception is returned to the client, but the request id is lost because the handler has no (easy) way to access it.

I know that with rabbitmq we can add "reply-to" header to every request that needs to be associated with a special reply (the rpc response), and this is implemented by creating a special temporary queue that the user is automatically subscribed to, but how may I use this scheme in Spring? Also, that would tie me a specific broker.

How may I elegantly implement a correct RPC call in Spring that correctly handles server side exceptions?

I find this a general problem and I think Spring could benefit greatly to implement it natively.

Alessandro Polverini
  • 2,301
  • 19
  • 29
  • A tentative solution that requires the modification of a Spring class is outlined here: https://github.com/spring-projects/spring-framework/pull/612 I'm still interested in a solution that does not require modification of Spring – Alessandro Polverini Aug 02 '14 at 16:14

2 Answers2

1

This not exactly what you demand, but maybe you can attempt something like this : Path variables in Spring WebSockets @SendTo mapping

You define an ID on your client and send id to the queue /user/queue/{myid} On the serveur side you will have a class who looks like this :

@MessageMapping("/user/queue/{myid}")
public void simple(@DestinationVariable String id, Object requestDto) {
    simpMessagingTemplate.convertAndSendToUser(userId, "/user/queue/" + id, responseDto);
}

This solution can work with the same principle as the rabbit mq solution you mention.

Hope this helps.

Community
  • 1
  • 1
Oreste Viron
  • 3,592
  • 3
  • 22
  • 34
0

If you do not need the exception/reason on the client, but only want to know which message failed you could send ack messages for successful messages. For successful messages you always have easy access to the message id / headers. By the absence of the ack message the client knows which message has failed.

Of course this comes at the costs of sending all the ack messages and knowing the timout of requests. Also additional code is required to keep track on the client side, but this can be done using a middleware and would end up in an ok-ish dev experience for the business logic.

Stuck
  • 11,225
  • 11
  • 59
  • 104