Merge branch 'feature/backend-websockets' into 'main'
Backend websockets See merge request cse1105/2025-2026/teams/csep-team-76!16
This commit is contained in:
commit
433f289c55
10 changed files with 242 additions and 8 deletions
33
server/src/main/java/server/WebSocketConfig.java
Normal file
33
server/src/main/java/server/WebSocketConfig.java
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package server;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
|
||||
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
|
||||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSocketMessageBroker
|
||||
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
|
||||
@Override
|
||||
public void configureMessageBroker(MessageBrokerRegistry registry) {
|
||||
|
||||
// SUBSCRIBE /subscribe/{mapping}, see UpdateMessagingController definition
|
||||
// adds a broker endpoint subscribers listen to
|
||||
registry.enableSimpleBroker("/subscribe");
|
||||
|
||||
// SEND /send/updates/{mapping}, see UpdateMessagingController definition
|
||||
// the client pushes a new message to this address
|
||||
registry.setApplicationDestinationPrefixes("/send");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
// a client can now push data to /send/updates/{mapping}, see UpdateMessagingController
|
||||
// allow access from any origin: one server, many clients
|
||||
registry.addEndpoint("/updates").setAllowedOrigins("*");
|
||||
// optional, recommended to increase browser & networking support
|
||||
registry.addEndpoint("/updates").setAllowedOrigins("*").withSockJS();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,15 @@ package server.api;
|
|||
|
||||
import commons.Recipe;
|
||||
|
||||
import commons.ws.Topics;
|
||||
import commons.ws.messages.CreateRecipeMessage;
|
||||
import commons.ws.messages.DeleteRecipeMessage;
|
||||
import commons.ws.messages.UpdateRecipeMessage;
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
|
@ -25,9 +30,11 @@ import java.util.Optional;
|
|||
@RequestMapping("/api")
|
||||
public class RecipeController {
|
||||
private final RecipeRepository recipeRepository; // JPA repository used in this controller
|
||||
private final SimpMessagingTemplate messagingTemplate;
|
||||
|
||||
public RecipeController(RecipeRepository recipeRepository) {
|
||||
public RecipeController(RecipeRepository recipeRepository, SimpMessagingTemplate messagingTemplate) {
|
||||
this.recipeRepository = recipeRepository;
|
||||
this.messagingTemplate = messagingTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -61,6 +68,7 @@ public class RecipeController {
|
|||
PageRequest.of(0, limit.get())
|
||||
).toList());
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(recipeRepository.findAll());
|
||||
}
|
||||
|
||||
|
|
@ -76,9 +84,10 @@ public class RecipeController {
|
|||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
|
||||
// TODO: Send WS update to all subscribers with the updated recipe
|
||||
Recipe saved = recipeRepository.save(recipe);
|
||||
messagingTemplate.convertAndSend(Topics.RECIPES, new UpdateRecipeMessage(saved));
|
||||
|
||||
return ResponseEntity.ok(recipeRepository.save(recipe));
|
||||
return ResponseEntity.ok(saved);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -104,9 +113,10 @@ public class RecipeController {
|
|||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
|
||||
// TODO: Send WS update to all subscribers with the new recipe
|
||||
Recipe saved = recipeRepository.save(recipe);
|
||||
messagingTemplate.convertAndSend(Topics.RECIPES, new CreateRecipeMessage(saved));
|
||||
|
||||
return ResponseEntity.ok(recipeRepository.save(recipe));
|
||||
return ResponseEntity.ok(saved);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -124,7 +134,8 @@ public class RecipeController {
|
|||
}
|
||||
recipeRepository.deleteById(id);
|
||||
|
||||
// TODO: Send WS update to propagate deletion
|
||||
messagingTemplate.convertAndSend(Topics.RECIPES, new DeleteRecipeMessage(id));
|
||||
|
||||
return ResponseEntity.ok(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
package server.api;
|
||||
|
||||
import commons.Recipe;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.messaging.handler.annotation.MessageMapping;
|
||||
import org.springframework.messaging.handler.annotation.SendTo;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
@Controller
|
||||
public class UpdateMessagingController {
|
||||
private final RecipeController recipeController;
|
||||
@Autowired
|
||||
public UpdateMessagingController(
|
||||
RecipeController recipeController) {
|
||||
this.recipeController = recipeController;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping for STOMP: <code>SEND /updates/recipe</code>
|
||||
* @param recipe The request body as a new {@link Recipe} object to update the original into
|
||||
* @return The updated {@link Recipe} object wrapped in a {@link org.springframework.http.ResponseEntity}.
|
||||
*/
|
||||
@MessageMapping("/updates/recipe")
|
||||
@SendTo("/subscribe/recipe")
|
||||
public ResponseEntity<Recipe> broadcastRecipeUpdate(Recipe recipe) {
|
||||
return recipeController.updateRecipe(recipe.getId(), recipe);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue