Starting WebSocket

This commit is contained in:
PEDSF 2020-11-05 18:25:17 +01:00
parent ad9d5f513c
commit 811f0852df
20 changed files with 201 additions and 60 deletions

View file

@ -17,16 +17,14 @@ import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerCo
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket")
.withSockJS();
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/websocket").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.setApplicationDestinationPrefixes("/app");
config.enableSimpleBroker("/topic/");
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic");
registry.setApplicationDestinationPrefixes("/app");
}
}

View file

@ -14,9 +14,10 @@ public class WebSocketSchedulerConfiguration {
@Autowired
SimpMessagingTemplate simpMessagingTemplate;
@Scheduled(fixedDelay = 3000)
//@Scheduled(fixedDelay = 3000)
public void sendMessages() {
simpMessagingTemplate.convertAndSend("/topic/user", new WebSocketMessage("Fixed Delay Scheduler"));
simpMessagingTemplate.convertAndSend("/topic/public", new WebSocketMessage("Fixed Delay Scheduler"));
}
}

View file

@ -19,6 +19,7 @@ import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonError;
import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
import org.springframework.samples.petclinic.dto.*;
import org.springframework.samples.petclinic.service.OwnerService;
import org.springframework.samples.petclinic.service.VisitService;
@ -41,7 +42,7 @@ import java.util.Map;
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@Controller
class OwnerController {
class OwnerController extends WebSocketSender {
private final OwnerService ownerService;
@ -68,10 +69,12 @@ class OwnerController {
public String processCreationForm(@ModelAttribute(CommonAttribute.OWNER) @Valid OwnerDTO owner,
BindingResult result) {
if (result.hasErrors()) {
sendMessages(CommonView.OWNER_CREATE_OR_UPDATE);
return CommonView.OWNER_CREATE_OR_UPDATE;
}
else {
owner = this.ownerService.save(owner);
sendMessages(OWNER_CREATED);
return CommonView.OWNER_OWNERS_R + owner.getId();
}
}
@ -79,6 +82,7 @@ class OwnerController {
@GetMapping(CommonEndPoint.OWNERS_FIND)
public String initFindForm(Map<String, Object> model) {
model.put(CommonAttribute.OWNER, new OwnerDTO());
return CommonView.OWNER_FIND_OWNERS;
}
@ -107,7 +111,8 @@ class OwnerController {
else {
// multiple owners found
model.put(CommonAttribute.SELECTIONS, results);
return CommonView.OWNER_OWNERS_LIST;
return CommonView.OWNER_OWNERS_LIST;
}
}
@ -127,6 +132,7 @@ class OwnerController {
else {
owner.setId(ownerId);
this.ownerService.save(owner);
sendMessages(OWNER_UPDATED);
return CommonView.OWNER_OWNERS_ID_R;
}
}

View file

@ -20,6 +20,7 @@ import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonError;
import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
import org.springframework.samples.petclinic.dto.*;
import org.springframework.samples.petclinic.validator.PetDTOValidator;
import org.springframework.samples.petclinic.service.*;
@ -41,7 +42,7 @@ import java.util.Collection;
*/
@Controller
@RequestMapping(CommonEndPoint.OWNERS_ID)
class PetController {
class PetController extends WebSocketSender {
private final OwnerService ownerService;
@ -100,6 +101,7 @@ class PetController {
}
else {
this.petService.save(pet);
sendMessages(PET_CREATED);
return CommonView.OWNER_OWNERS_ID_R;
}
}
@ -122,6 +124,7 @@ class PetController {
else {
owner.addPet(pet);
this.petService.save(pet);
sendMessages(PET_UPDATED);
return CommonView.OWNER_OWNERS_ID_R;
}
}

View file

@ -18,6 +18,7 @@ package org.springframework.samples.petclinic.controller;
import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
import org.springframework.samples.petclinic.dto.VetsDTO;
import org.springframework.samples.petclinic.service.VetService;
import org.springframework.stereotype.Controller;

View file

@ -22,6 +22,7 @@ import javax.validation.Valid;
import org.springframework.samples.petclinic.common.CommonAttribute;
import org.springframework.samples.petclinic.common.CommonEndPoint;
import org.springframework.samples.petclinic.common.CommonView;
import org.springframework.samples.petclinic.controller.common.WebSocketSender;
import org.springframework.samples.petclinic.dto.PetDTO;
import org.springframework.samples.petclinic.dto.VisitDTO;
import org.springframework.samples.petclinic.service.PetService;
@ -46,7 +47,7 @@ import org.springframework.web.bind.annotation.PostMapping;
* @author Paul-Emmanuel DOS SANTOS FACAO
*/
@Controller
class VisitController {
class VisitController extends WebSocketSender {
private final VisitService visitService;
@ -99,6 +100,7 @@ class VisitController {
}
else {
this.visitService.save(visit);
sendMessages(VISIT_CREATED);
return CommonView.OWNER_OWNERS_ID_R;
}
}

View file

@ -1,19 +0,0 @@
package org.springframework.samples.petclinic.controller.common;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.samples.petclinic.model.common.User;
import org.springframework.samples.petclinic.model.common.WebSocketMessage;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
@MessageMapping("/user")
@SendTo("/topic/user")
public WebSocketMessage getUser(User user) {
return new WebSocketMessage("Hi " + user.getFirstName() + user.getLastName());
}
}

View file

@ -7,11 +7,10 @@ import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.samples.petclinic.model.common.WebSocketMessage;
import org.springframework.stereotype.Controller;
@Controller
public class WebSocketController {
@MessageMapping("/websocket.send")
@SendTo("/topic/public")
@MessageMapping("/user")
@SendTo("/topic/user")
public WebSocketMessage sendMessage(@Payload final WebSocketMessage message) {
return message;
}
@ -19,7 +18,7 @@ public class WebSocketController {
@MessageMapping("/websocket.newUser")
@SendTo("/topic/public")
public WebSocketMessage newUser(@Payload final WebSocketMessage message, SimpMessageHeaderAccessor headerAccessor) {
headerAccessor.getSessionAttributes().put("usqername", message.getSender());
headerAccessor.getSessionAttributes().put("username", message.getSender());
return message;
}

View file

@ -26,8 +26,10 @@ public class WebSocketEventListener {
final StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
final String username = (String) headerAccessor.getSessionAttributes().get("username");
// final String username = (String)
// headerAccessor.getSessionAttributes().get("username");
sendingOperations.convertAndSend("/topic/public", new WebSocketMessage("Hello" + username));
sendingOperations.convertAndSend("/topic/user", new WebSocketMessage("Hello in event lmistener"));
}
}

View file

@ -0,0 +1,31 @@
package org.springframework.samples.petclinic.controller.common;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.samples.petclinic.model.common.WebSocketMessage;
public class WebSocketSender {
public static final String OWNER_CREATED = "Owner created";
public static final String OWNER_UPDATED = "Owner updated";
public static final String OWNER_DELETED = "Owner deleted";
public static final String PET_CREATED = "Pet created";
public static final String PET_UPDATED = "Pet updated";
public static final String PET_DELETED = "Pet deleted";
public static final String VET_CREATED = "Vet created";
public static final String VET_UPDATED = "Vet updated";
public static final String VET_DELETED = "Vet deleted";
public static final String VISIT_CREATED = "Visit created";
public static final String VISIT_UPDATED = "Visit updated";
public static final String VISIT_DELETED = "Visit deleted";
@Autowired
SimpMessagingTemplate simpMessagingTemplate;
public void sendMessages(String message) {
simpMessagingTemplate.convertAndSend("/topic/public", new WebSocketMessage(message));
}
}

View file

@ -1,10 +0,0 @@
package org.springframework.samples.petclinic.model.common;
import org.springframework.samples.petclinic.model.Person;
public class User extends Person {
public User() {
super();
}
}

View file

@ -1,6 +1,5 @@
package org.springframework.samples.petclinic.model.common;
import java.time.LocalDate;
public class WebSocketMessage {
@ -11,7 +10,6 @@ public class WebSocketMessage {
private String content;
public WebSocketMessage(String content) {
this.time = LocalDate.now().toString();
this.content = content;
@ -40,4 +38,5 @@ public class WebSocketMessage {
public void setContent(String content) {
this.content = content;
}
}

View file

@ -1,7 +1,7 @@
package org.springframework.samples.petclinic.model.common;
public enum WebSocketMessageType {
MESSAGE,
CONNECT,
DISCONNECT
MESSAGE, CONNECT, DISCONNECT
}

View file

@ -6,3 +6,7 @@ nonNumeric=must be all numeric
duplicateFormSubmission=Duplicate form submission is not allowed
typeMismatch.date=invalid date
typeMismatch.birthDate=invalid date
english=English
french=French
german=German
spanish=Spanish

View file

@ -6,3 +6,7 @@ nonNumeric=darf nur numerisch sein
duplicateFormSubmission=Wiederholtes Absenden des Formulars ist nicht erlaubt
typeMismatch.date=ungültiges Datum
typeMismatch.birthDate=ungültiges Datum
english=Englisch
french=Französisch
german=Deutsche
spanish=Spanisch

View file

@ -1,8 +1,12 @@
welcome=Bienvenido
required=Es requerido
required=es requerido
notFound=No ha sido encontrado
duplicate=Ya se encuentra en uso
nonNumeric=Sólo debe contener numeros
duplicateFormSubmission=No se permite el envío de formularios duplicados
typeMismatch.date=Fecha invalida
typeMismatch.date=fecha invalida
typeMismatch.birthDate=Fecha invalida
english=Ingl\u00E9s
french=Franc\u00E9s
german=Alemán
spanish=Espa\u00F1ol

View file

@ -0,0 +1,12 @@
welcome=Bienvenue
required=est requis
notFound=n'a pas \u00E9t\u00E9 trouv\u00E9
duplicate=d\u00E9jà utilis\u00E9
nonNumeric=doit être num\u00E9rique
duplicateFormSubmission=La duplication de formulaire n'est pas autoris\u00E9e
typeMismatch.date=date non valide
typeMismatch.birthDate=date non valide
english=Anglais
french=Fran\u00E7ais
german=Allemand
spanish=Espagnol

View file

@ -0,0 +1,7 @@
#footer {
position:absolute;
bottom:0;
width:100%;
height:60px; /* Height of the footer */
background:#6cf;
}

View file

@ -0,0 +1,62 @@
var stompClient = null;
function setConnected(connected) {
$("#connect").prop("disabled", connected);
$("#disconnect").prop("disabled", !connected);
if (connected) {
$("#conversation").show();
}
else {
$("#conversation").hide();
}
$("#userinfo").html("");
}
function displayMessage() {
var socket = new SockJS('/websocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
stompClient.subscribe('/topic/public', function (greeting) {
showGreeting(JSON.parse(greeting.body).content);
});
});
}
function connect() {
var socket = new SockJS('/websocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/public', function (greeting) {
$("#userinfo").text(JSON.parse(greeting.body).content);
});
});
}
function disconnect() {
if (stompClient !== null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
function sendName() {
stompClient.send("/app/user", {}, JSON.stringify({'name': $("#name").val()}));
}
function showGreeting(message) {
$("#userinfo").text(message);
}
$(function () {
$("form").on('submit', function (e) {
e.preventDefault();
});
$( "#connect" ).click(function() { connect(); });
$( "#disconnect" ).click(function() { disconnect(); });
$( "#send" ).click(function() { sendName(); });
});

View file

@ -18,6 +18,7 @@
<![endif]-->
<link rel="stylesheet" th:href="@{/resources/css/petclinic.css}" />
<link rel="stylesheet" th:href="@{/resources/static/css/style.css}" />
</head>
@ -78,6 +79,8 @@
</div>
</div>
</nav>
<div class="container-fluid">
<div class="container xd-container">
@ -86,18 +89,50 @@
<br />
<br />
<div class="container">
<div class="row">
<div class="col-12 text-center">
<img src="../static/resources/images/spring-pivotal-logo.png"
th:src="@{/resources/images/spring-pivotal-logo.png}" alt="Sponsored by Pivotal" /></div>
</div>
</div>
</div>
</div>
<footer class="navbar" style="position:absolute; bottom:0; width:100%;">
<div id="main-content" class="container">
<div class="row">
<form class="form-inline">
<div class="form-group pull-left" id="conversation">
<span id="messageOutput" class="form-control" style="width:200px; "></span>
</div>
<div class="form-group pull-right" >
<img src="../static/resources/images/spring-pivotal-logo.png"
th:src="@{/resources/images/spring-pivotal-logo.png}" alt="Sponsored by Pivotal" />
</div>
</form>
</div>
</div>
</footer>
<script th:src="@{/webjars/jquery/jquery.min.js}"></script>
<script th:src="@{/webjars/jquery-ui/jquery-ui.min.js}"></script>
<script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
<script th:src="@{/webjars/sockjs-client/sockjs.min.js}"></script>
<script th:src="@{/webjars/stomp-websocket/stomp.min.js}"></script>
<script type="text/javascript">
$(document).ready( function(){
var socket = new SockJS('/websocket');
var stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
stompClient.subscribe('/topic/public', function (socketMessage) {
var message = JSON.parse(socketMessage.body).content;
alert(message);
$('#messageOutput').text(message);
});
});
});
</script>
</body>