Reputation: 851
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
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