Kshitij Bajracharya
Kshitij Bajracharya

Reputation: 851

Notify specific user using web socket in spring boot

I am creating a task management application in Spring boot. Following are my models:

public class Task {

    private String name;
    private String description;
    private User assignee;

    //getters and setters
}

public class User {

    private String name;
    private String email;
    private String password;

    //getters and setters
}

I'm using spring security for the user. Now say there are three Users A, B and C. A creates a Task and assigns it to B. I am trying to send a notification only to B at this point using websocket. For this I created a WebSocketConfiguration:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer {
    @Override
    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        stompEndpointRegistry.addEndpoint("/socket").setAllowedOrigins("*").withSockJS();
    }

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

The controller to assign this task:

@RestController
@RequestMapping("/api/task")
public class TaskController {

    @PostMapping("/assign")
    public void assign(@RequestBody Task task) {
        taskService.assign(task);
    }
}

And finally in the service, I have:

@Service
public class TaskService {

    @Autowired
    private SimpMessagingTemplate template;

    @Override
    public void assign(Task task) {
        //logic to assign task
        template.convertAndSendToUser(task.getAssignee().getEmail(), "/topic/notification",
            "A task has been assigned to you");
    }
}

In the client side, I'm using Angular and the subscribe portion looks like the following:

stompClient.subscribe('/topic/notification'+logged_user_email, notifications => {
    console.log(notifications); 
})

Currently, nothing is printed in the console for any of the users.

I followed this tutorial, which worked perfectly for broadcast message.

I've also used this answer as a reference for using the logged_user_email, but it doesn't work.

I've tried prefixing /user to subscribe to /user/topic/notification/ in client side as explained in this answer. I've also tried using queue instead of topic as explained in the same answer, but I have found no success.

Other answers I've found mention the use of @MessageMapping in the controller but I need to be able to send the notification from the service.

So the question is how do I distinguish which user the notification is intended for and how do I define this in both the server and client sides?

Upvotes: 3

Views: 1372

Answers (1)

Kshitij Bajracharya
Kshitij Bajracharya

Reputation: 851

This may be a bit late but for anyone who's having the same problem, I made it working by doing the following:

Instead of sending the email of the user, I converted it to Base64 and sent.

@Service
public class TaskService {

    @Autowired
    private SimpMessagingTemplate template;

    @Override
    public void assign(Task task) {
        //logic to assign task
        String base64EncodedEmail = Base64.getEncoder().encodeToString(task.getAssignee().getEmail().getBytes(StandardCharsets.UTF_8));
        template.convertAndSendToUser(base64EncodedEmail, "/topic/notification",
            "A task has been assigned to you");
    }
}

Then in the client side, in the WebSocketService of this tutorial, I replaced the connect method with the following:

public connect() {
    const encodedEmail = window.btoa(email);
    const socket = new SockJs(`http://localhost:8080/socket?token=${encodedEmail}`);
    const stompClient = Stomp.over(socket);
    return stompClient;
}

In the subscribe section, I did the following:

stompClient.subscribe("/user/topic/notification", notification => {
    //logic to display notification
});

Everything else is same as in the tutotial.

Upvotes: 0

Related Questions