stomp - Does Spring @SubscribeMapping really subscribe the client to some topic? -


i using spring websocket stomp, simple message broker. in @controller use method-level @subscribemapping, should subscribe client topic client receive messages of topic afterwards. let say, client subscribes topic "chat":

stompclient.subscribe('/app/chat', ...);

as client subscribed "/app/chat", instead of "/topic/chat", subscription go method mapped using @subscribemapping:

@subscribemapping("/chat") public list getchatinit() {     return chat.getusers(); } 

here spring ref. says:

by default return value @subscribemapping method sent message directly connected client , not pass through broker. useful implementing request-reply message interactions; example, fetch application data when application ui being initialized.

okay, want, partially!! sending init-data after subscribing, well. subscribing? seems me thing happened here request-reply, service. subscription consumed. please clarify me if case.

  • did client subscribe where, if broker not involved in this?
  • if later want send message "chat" subscriptors, client receive it? doesnt seem so.
  • who realizes subscriptions really? broker? or 1 else?

if here client not being subscribed where, wonder why call "subscribe"; because client receives 1 message , not future messages.

edit:

to make sure subscription has been realized, tried following:

server-side:

configuration:

@configuration @enablewebsocketmessagebroker public class websocketconfig extends abstractwebsocketmessagebrokerconfigurer {      @override     public void configuremessagebroker(messagebrokerregistry config) {         config.enablesimplebroker("/topic");         config.setapplicationdestinationprefixes("/app");     }      @override     public void registerstompendpoints(stompendpointregistry registry) {         registry.addendpoint("/hello").withsockjs();     } } 

controller:

@controller public class greetingcontroller {      @messagemapping("/hello")     @sendto("/topic/greetings")     public greeting greeting(hellomessage message) throws exception {         system.out.println("inside greeting");         return new greeting("hello, " + message.getname() + "!");     }      @subscribemapping("/topic/greetings")     public greeting try1() {         system.out.println("inside try 1");         return new greeting("hello, " + "try 1" + "!");     } } 

client-side:

...     stompclient.subscribe('/topic/greetings', function(greeting){                         console.log('received !!!');                     });     stompclient.send("/app/hello", {}, json.stringify({ 'name': name })); ... 

what happen:

  1. when client subscribes '/topic/greetings', method try1 executed.
  2. when client sends msg '/app/hello', should receive greetings msg @sendto '/topic/greetings'.

results:

  1. if client subscribes /topic/greetings, method try1 unable catch it.

  2. when client sends msg '/app/hello', greeting method executed, , client received greetings message. understood had been subscribed '/topic/greetings' correctly.

  3. but remember 1. failed. after try, has been possible when client subscribed '/app/topic/greetings', i.e. prefixed /app (this understandable configuration).

  4. now 1. working, time 2. failed: when client sends msg '/app/hello', yes, greeting method executed, client did not receive greetings message. (because client subscribed topic prefixed '/app', unwanted.)

so, got either 1 or 2 of like, not these 2 together.

  • how achieve this structure (configuring mapping paths correctly) ?

by default return value @subscribemapping method sent message directly connected client , does not pass through broker.

(emphasis mine)

here spring framework documentation describing happens response message, not incoming subscribe message.

so answer questions:

  • yes, client subscribed topic
  • yes, clients subscribed topic receive message if use topic send it
  • the message broker in charge of managing subscriptions

more on subscription management

with simplemessagebroker, message broker implementation lives in application instance. subscription registrations managed defaultsubscriptionregistry. when receiving messages, simplebrokermessagehandler handles subscription messages , register subscriptions (see implementation here).

with "real" message broker rabbitmq, you've configured stomp broker relay forwards messages broker. in case, subscribe messages forwarded broker, in charge of managing subscriptions (see implementation here).

update - more on stomp message flow

if take @ the reference documentation on stomp message flow, you'll see that:

  • subscriptions "/topic/greeting" pass through "clientinboundchannel" , forwarded broker
  • greetings sent "/app/greeting" pass through "clientinboundchannel" , forwarded greetingcontroller. controller adds current time, , return value passed through "brokerchannel" message "/topic/greeting" (destination selected based on convention can overridden via @sendto).

so here, /topic/hello broker destination; messages sent there directly forwarded broker. while /app/hello application destination, , supposed produce message sent /topic/hello, unless @sendto says otherwise.

now updated question somehow different one, , without more precise use case it's difficult pattern best solve this. here few:

  • you want client aware whenever happens, asynchronously: subscribe particular topic /topic/hello
  • you want broadcast message: send message particular topic /topic/hello
  • you want immediate feedback something, example initialize state of application: subscribe application destination /app/hello controller responding message right away
  • you want send 1 or more messages application destination /app/hello: use combination of @messagemapping, @sendto or messaging template.

if want example, check out this chat application demonstrating log of spring websocket features real world use case.


Comments

Popular posts from this blog

node.js - Mongoose: Cast to ObjectId failed for value on newly created object after setting the value -

gradle error "Cannot convert the provided notation to a File or URI" -

python - NameError: name 'subprocess' is not defined -