2

I have following code on server side:

@Autowired
private SimpMessagingTemplate simpMessagingTemplate;

@MessageMapping("/hello")
public void greeting(@Payload HelloMessage message, Principal principal) throws Exception {
    Thread.sleep(1000); // simulated delay
    simpMessagingTemplate.convertAndSendToUser(principal.getName(), "/topic/greetings", new Greeting("Ololo"));        
}

client side code:

function connect() {
    var socket = new SockJS('/gs-guide-websocket');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function (frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function (greeting) {
            showGreeting(JSON.parse(greeting.body).content);
        });
    });
}
function showGreeting(message) {
    $("#greetings").append("<tr><td>" + message + "</td></tr>");
}

My actions:

I run application, log in as user1 and initiate message sending from client to server and I see that method greeting is invokes and line simpMessagingTemplate.convertAndSendToUser(principal.getName(), "/topic/greetings", new Greeting("Ololo")) executes successfully but I don't see that message on the client side.

How can I

more sources:

spring security configuration:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private static final String SECURE_ADMIN_PASSWORD = "rockandroll";

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .formLogin()
                .loginPage("/index.html")
                    .loginProcessingUrl("/login")
                    .defaultSuccessUrl("/sender.html")
                    .permitAll()
                .and()
                .logout()
                    .logoutSuccessUrl("/index.html")
                    .permitAll()
                .and()
                .authorizeRequests()
                .antMatchers("/js/**", "/lib/**", "/images/**", "/css/**", "/index.html", "/","/*.css","/webjars/**", "/*.js").permitAll()
                .antMatchers("/websocket").hasRole("ADMIN")
                .requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ADMIN")
                .anyRequest().authenticated();

    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        auth.authenticationProvider(new AuthenticationProvider() {

            @Override
            public boolean supports(Class<?> authentication) {
                return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
            }

            @Override
            public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;

                List<GrantedAuthority> authorities = SECURE_ADMIN_PASSWORD.equals(token.getCredentials()) ?
                        AuthorityUtils.createAuthorityList("ROLE_ADMIN") : null;

                return new UsernamePasswordAuthenticationToken(token.getName(), token.getCredentials(), authorities);
            }
        });
    }
}

web socket config:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/gs-guide-websocket").withSockJS();
    }

}

update

After advices and reading topic Sending message to specific user on Spring Websocket I tried following:

1.

server side:

simpMessagingTemplate.convertAndSendToUser("user1", "/queue/greetings", new Greeting("Ololo"));

client side:

stompClient.subscribe('/user1/queue/greetings', function(menuItem){
    alert(menuItem);
});

2.

server side:

simpMessagingTemplate.convertAndSendToUser("user1", "/queue/greetings", new Greeting("Ololo"));

client side:

stompClient.subscribe('/user/queue/greetings', function(menuItem){
    alert(menuItem);
});

3.

server side:

simpMessagingTemplate.convertAndSendToUser("user1", "/queue/greetings", new Greeting("Ololo"));

client side:

stompClient.subscribe('user/user1/queue/greetings', function(menuItem){
    alert(menuItem);
});

It doesn't work anyway

10
  • Do you see on the developer console of your browser (a) "Connected: ..." on opening the application in your browser , (b) "... Ololo .." after server sends its message? If you see the initial "Connected", but not the "Ololo", then you may not subscribe to the correct target. Should the target not start with "/user" instead of "topic"? Commented Apr 26, 2018 at 14:30
  • @Markus Pscheidt subscription in browser happens successfully - I checked it. I modified code a bit github.com/gredwhite/demo_ws_app/blob/master/src/main/java/… and it sends message only Hello ... Commented Apr 26, 2018 at 14:36
  • @Markus Pscheidt should I subscribe on user specific queue sepratedly? Commented Apr 26, 2018 at 14:39
  • You receive "Hello.." because the client subscribed to /topic/greetings and @SendTo("/topic/greetings") public Greeting greeting(...) delivers a message to this queue. You might have success in subscribing to /user/user1/topic/greetings, because that's where simpMessagingTemplate.convertAndSendToUser(principal.getName(), "/topic/greetings", new Greeting("Ololo")) seems to deliver to. Commented Apr 26, 2018 at 14:46
  • 1
    @Markus Pscheidt, I did it. Can you look at github.com/gredwhite/demo_ws_app/tree/master/src ? Commented Apr 26, 2018 at 16:16

2 Answers 2

2

Only necessary change is on the client (app.js): Instead of /user/user1/queue/greetings, subscribe to /user/queue/greetings:

stompClient.subscribe('/user/queue/greetings', ...

Then login as user1 in the web interface. It has to be user1 because that's the user that is targeted at the server:

convertAndSendToUser("user1", "/queue/greetings", new Greeting("Ololo")) 

Upon clicking Send, The Ololo message appears as a client alert.

Sign up to request clarification or add additional context in comments.

4 Comments

So "user1" would be the username returned by userservice.loadUserByUsername right in Spring, right? Would it be possible to do something like this: When there is an update to a child, get the usernames of the parents of that child, and run convertAndSendToUser(username, /queue/updates ... ) for each parents username.
You are free to send a message to any user, so why not sending to the users that happen to be the parents of a specific child. When a parent is logged in, he/she receives the message
thanks! And just while I've got your attention, I can use a similar approach with convertAndSend("any/topic/at/all", message) to send a message from anywhere in the application (services etc) to subscribers of topic/any/topic/at/all, yeah? ( I'm thinking how to update subscribers if a resource is changed through a REST call rather than through the messagemapper method.)
That's right, sending messages from anywhere in the system, including services, is possible, as long as the messaging template is available.
1

it works with me now under

template.convertAndSendToUser("username","/queue/notification",notifications); //server

stompClient.subscribe('/user/username/queue/notification', ....  // client

thanks every body

1 Comment

For me too. Thanx!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.