i am working for my first time with websockets , i am trying to create an application that sends global notifications that everyone can see and also private notifications for specific users from Database. So i have implemented a WebSocket Configuration and sending notifications to everyone works fine but sending private notifications messages to specific user from database did not work , when i open two browsers windows i can not see the private notification coming while i can see the global one.
Here My WebSocket Configuration file:
@Configuration @EnableWebSocketMessageBroker public class
WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
//web sockets starts communication with /notification
registry.enableSimpleBroker("/topic");
//web socket prefix
registry.setApplicationDestinationPrefixes("/ws");
}
//to use in front end
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
//front end starts with this url to communicate with web socket
registry.addEndpoint("/ws-notifications")
.withSockJS();
} }
NotificationsController:
@Controller
public class NotificationsController {
@Autowired
private NotificationService notificationService;
@Autowired
NotificationRepository notificationRepository;
@MessageMapping("/message")
@SendTo("/topic/messages")
public ResponseNotification getMessage(final NotificationDAO notificationDAO) throws InterruptedException {
Thread.sleep(1000);
notificationService.sendGlobalNotification();
return new ResponseNotification("Hello, " + HtmlUtils.htmlEscape(notificationDAO.getMessageContent()) + "!");
}
@MessageMapping("/private-message")
@SendTo("/topic/private-messages")
public ResponseNotification getPrivateMessage(final NotificationDAO notificationDAO, final Principal principal) throws
InterruptedException {
Thread.sleep(1000);
notificationService.sendPrivateNotification(principal.getName());
return new ResponseNotification("Sending private message to user "+principal.getName()+ " : " +
HtmlUtils.htmlEscape(notificationDAO.getMessageContent()) + "!");
}
}
NotificationsService:
@Service
public class NotificationService implements INotificationService {
String apiBaseUrl = "https://api.github.com";
private final SimpMessagingTemplate messagingTemplate;
@Autowired public NotificationService(SimpMessagingTemplate
messagingTemplate) { this.messagingTemplate = messagingTemplate;
}
public void sendGlobalNotification() { ResponseNotification
message = new ResponseNotification("Global Notification");
messagingTemplate.convertAndSend("/topic/global-notifications",
message); }
public void sendPrivateNotification(final String userId) {
ResponseNotification message = new ResponseNotification("Private
Notification");
messagingTemplate.convertAndSendToUser(userId,"/topic/private-notifications",
message); } }
WebSocketController:
@RestController
@RequestMapping("api/websocket") public class
WebSocketController {
@Autowired
WebSocketService webSocketService;
@PostMapping("/send-message")
public void sendMessage(@RequestBody final NotificationDAO notificationDAO) {
webSocketService.notifyFrontend(notificationDAO.getMessageContent());
}
@PostMapping("/send-private-message/{id}")
public void sendPrivateMessage(@PathVariable final String id, @RequestBody final
NotificationDAO notificationDAO) {
webSocketService.notifyUser(id,notificationDAO.getMessageContent());
}
My WebSocketService:
@Service
public class WebSocketService {
private final SimpMessagingTemplate messagingTemplate;
private final NotificationService notificationService;
@Autowired
public WebSocketService(SimpMessagingTemplate messagingTemplate, NotificationService notificationService) {
this.messagingTemplate = messagingTemplate;
this.notificationService = notificationService;
}
public void notifyFrontend(final String message) {
ResponseNotification responseNotification = new ResponseNotification(message);
notificationService.sendGlobalNotification();
messagingTemplate.convertAndSend("topic/messages",responseNotification);
}
public void notifyUser(final String id, final String message) {
ResponseNotification responseNotification = new ResponseNotification(message);
notificationService.sendPrivateNotification(id);
messagingTemplate.convertAndSendToUser(id,"topic/private-messages",responseNotification);
}
}
My WebSocketService:
@Service public class WebSocketService {
private final SimpMessagingTemplate messagingTemplate;
private final NotificationService notificationService;
@Autowired
public WebSocketService(SimpMessagingTemplate messagingTemplate, NotificationService notificationService) {
this.messagingTemplate = messagingTemplate;
this.notificationService = notificationService;
}
public void notifyFrontend(final String message) {
ResponseNotification responseNotification = new ResponseNotification(message);
notificationService.sendGlobalNotification();
messagingTemplate.convertAndSend("topic/messages",responseNotification);
}
public void notifyUser(final String id, final String message) {
ResponseNotification responseNotification = new ResponseNotification(message);
notificationService.sendPrivateNotification(id);
messagingTemplate.convertAndSendToUser(id,"topic/private-messages",responseNotification);
}
}
my js file:
var stompClient = null; var notificationCount = 0;
$(document).ready( function () {
console.log("document is ready")
$("form").on('submit', function (e) {
e.preventDefault();
});
$( "#connect" ).click(function() { connect(); });
$( "#disconnect" ).click(function() { disconnect(); });
$( "#send" ).click(function() { sendMessage(); });
$( "#send-private" ).click(function() { sendPrivateMessage(); });
$( "#notifications" ).click(function() { resetNotificationCount(); });
});
function setConnected(connected) {
$("#connect").prop("disabled", connected);
$("#disconnect").prop("disabled", !connected);
if (connected) {
$("#conversation").show();
}
else {
$("#conversation").hide();
}
$("#greetings").html(""); }
function connect() {
var socket = new SockJS('/ws-notifications');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
console.log('Connected: ' + frame);
updateNotificationDisplay();
stompClient.subscribe('/topic/messages', function (message) {
showMessage(JSON.parse(message.body).content);
});
stompClient.subscribe('/topic/private-messages', function (message) {
showMessage(JSON.parse(message.body).content);
});
stompClient.subscribe('/topic/global-notifications', function (message) {
notificationCount = notificationCount + 1;
updateNotificationDisplay();
});
stompClient.subscribe('/topic/private-notifications', function (message) {
notificationCount = notificationCount + 1;
updateNotificationDisplay();
});
});
}
function disconnect() {
if (stompClient !== null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected"); }
function showMessage(message) {
$("#messages").append("<tr><td>" + message + "</td></tr>"); }
function sendMessage() {
console.log("sending message");
stompClient.send("/ws/message", {}, JSON.stringify({'messageContent': $("#message").val()})); }
function sendPrivateMessage() {
console.log("sending private message");
stompClient.send("/ws/private-message", {}, JSON.stringify({'messageContent': $("#private-message").val()})); }
function updateNotificationDisplay() {
if (notificationCount == 0) {
$('#notifications').hide();
} else {
$('#notifications').show();
$('#notifications').text(notificationCount);
} }
function resetNotificationCount() {
notificationCount = 0;
updateNotificationDisplay(); }
My question is how to send a private message to a user with username for example david20 and how david20 can see his private notifications and on what url?
i have already spring security implemented on the application and i am not sure if authentication is required or not to send/get private messages. I am fully lost and i almost understand a little about webSocket. Any help will be so appreciated.