From 299385c7b182de78a327ca88b55d9e15ee95c952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Rasie=C5=84ski?= Date: Wed, 7 Jan 2026 23:23:20 +0100 Subject: [PATCH 1/9] Created recipe service. --- .../server/database/RecipeRepository.java | 4 +- .../src/main/java/service/RecipeService.java | 87 +++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 server/src/main/java/service/RecipeService.java diff --git a/server/src/main/java/server/database/RecipeRepository.java b/server/src/main/java/server/database/RecipeRepository.java index 60ec130..8657873 100644 --- a/server/src/main/java/server/database/RecipeRepository.java +++ b/server/src/main/java/server/database/RecipeRepository.java @@ -19,4 +19,6 @@ import org.springframework.data.jpa.repository.JpaRepository; import commons.Recipe; -public interface RecipeRepository extends JpaRepository {} \ No newline at end of file +public interface RecipeRepository extends JpaRepository { + boolean existsByName(String name); +} \ No newline at end of file diff --git a/server/src/main/java/service/RecipeService.java b/server/src/main/java/service/RecipeService.java new file mode 100644 index 0000000..57cdf16 --- /dev/null +++ b/server/src/main/java/service/RecipeService.java @@ -0,0 +1,87 @@ +package service; + +import commons.Recipe; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; +import server.database.IngredientRepository; +import server.database.RecipeIngredientRepository; +import server.database.RecipeRepository; + +import java.util.List; +import java.util.Optional; + +@Service +public class RecipeService { + RecipeRepository recipeRepository; + IngredientRepository ingredientRepository; + RecipeIngredientRepository recipeIngredientRepository; + + public RecipeService(RecipeRepository recipeRepository, + IngredientRepository ingredientRepository, + RecipeIngredientRepository recipeIngredientRepository) { + this.recipeRepository = recipeRepository; + this.ingredientRepository = ingredientRepository; + this.recipeIngredientRepository = recipeIngredientRepository; + } + + Optional findById(Long id) { + return recipeRepository.findById(id); + } + + List findAll() { + return recipeRepository.findAll(); + } + + List findAll(int limit) { + return recipeRepository.findAll(PageRequest.of(0, limit)).toList(); + } + + /** + * Creates a new recipe. Returns empty if the recipe with the same name already exists. + * @param recipe Recipe to be saved in the db. + * @return The created recipe (the recipe arg with a new assigned id). + */ + public Optional create(Recipe recipe) { + if (recipeRepository.existsByName(recipe.getName())) { + return Optional.empty(); + } + + return Optional.of(saveWithDependencies(recipe)); + } + + /** + * Updates a recipe. The recipe with the provided id will be replaced with the provided recipe. + * Automatically updates ingredients and any dependencies of recipe. + * @param id id of the recipe to update. + * @param recipe Recipe to be saved in the db. + * @return The created recipe (the recipe arg with a new assigned id.) + */ + public Optional update(Long id, Recipe recipe) { + assert id.equals(recipe.getId()) : "The id of the updated recipe doesn't match the provided recipes id."; + if (!recipeRepository.existsById(id)) { + return Optional.empty(); + } + + return Optional.of(saveWithDependencies(recipe)); + } + + public void delete(Long id) { + // TODO: Propagate deletion to ingredients. + recipeRepository.deleteById(id); + } + + private Recipe saveWithDependencies(Recipe recipe) { + // TODO: try to automate this with JFX somehow. + recipe.getIngredients() + .forEach(recipeIngredient -> + recipeIngredient.setIngredient( + ingredientRepository + .findByName(recipeIngredient.getIngredient().name) + .orElseGet(() -> ingredientRepository.save(recipeIngredient.getIngredient()) + )) + ); + recipeIngredientRepository.saveAll(recipe.getIngredients()); + return recipeRepository.save(recipe); + } + +} From d56b07f2aa8b7976a2713cc69b54a726ec44cef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Rasie=C5=84ski?= Date: Wed, 7 Jan 2026 23:46:40 +0100 Subject: [PATCH 2/9] comment and access fixes for RecipeService --- server/src/main/java/service/RecipeService.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/service/RecipeService.java b/server/src/main/java/service/RecipeService.java index 57cdf16..1c0ea4e 100644 --- a/server/src/main/java/service/RecipeService.java +++ b/server/src/main/java/service/RecipeService.java @@ -24,22 +24,22 @@ public class RecipeService { this.recipeIngredientRepository = recipeIngredientRepository; } - Optional findById(Long id) { + public Optional findById(Long id) { return recipeRepository.findById(id); } - List findAll() { + public List findAll() { return recipeRepository.findAll(); } - List findAll(int limit) { + public List findAll(int limit) { return recipeRepository.findAll(PageRequest.of(0, limit)).toList(); } /** * Creates a new recipe. Returns empty if the recipe with the same name already exists. * @param recipe Recipe to be saved in the db. - * @return The created recipe (the recipe arg with a new assigned id). + * @return The created recipe (the recipe arg with a new assigned id) or empty if it already exists in db. */ public Optional create(Recipe recipe) { if (recipeRepository.existsByName(recipe.getName())) { From 032b86e502478b1b426df4d19a6a9537a8a9de71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Rasie=C5=84ski?= Date: Wed, 7 Jan 2026 23:46:57 +0100 Subject: [PATCH 3/9] created getters for Ingredient --- commons/src/main/java/commons/Ingredient.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/commons/src/main/java/commons/Ingredient.java b/commons/src/main/java/commons/Ingredient.java index 207d568..dd93aab 100644 --- a/commons/src/main/java/commons/Ingredient.java +++ b/commons/src/main/java/commons/Ingredient.java @@ -72,6 +72,26 @@ public class Ingredient { this.id = id; } + public double getProteinPer100g() { + return proteinPer100g; + } + + public double getFatPer100g() { + return fatPer100g; + } + + public double getCarbsPer100g() { + return carbsPer100g; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + @Override public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; From b7116a0882ab81e750f1c0b939cb70a1d40821f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Rasie=C5=84ski?= Date: Wed, 7 Jan 2026 23:49:42 +0100 Subject: [PATCH 4/9] Created IngredientService --- .../server/database/IngredientRepository.java | 2 + .../main/java/service/IngredientService.java | 65 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 server/src/main/java/service/IngredientService.java diff --git a/server/src/main/java/server/database/IngredientRepository.java b/server/src/main/java/server/database/IngredientRepository.java index df54bd3..ba90987 100644 --- a/server/src/main/java/server/database/IngredientRepository.java +++ b/server/src/main/java/server/database/IngredientRepository.java @@ -12,5 +12,7 @@ public interface IngredientRepository extends JpaRepository { List findAllByOrderByNameAsc(); Page findAllByOrderByNameAsc(Pageable pageable); Optional findByName(String name); + + boolean existsByName(String name); } diff --git a/server/src/main/java/service/IngredientService.java b/server/src/main/java/service/IngredientService.java new file mode 100644 index 0000000..a519107 --- /dev/null +++ b/server/src/main/java/service/IngredientService.java @@ -0,0 +1,65 @@ +package service; + +import commons.Ingredient; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; +import server.database.IngredientRepository; + +import java.util.List; +import java.util.Optional; + +@Service +public class IngredientService { + IngredientRepository ingredientRepository; + + public IngredientService(IngredientRepository ingredientRepository) { + this.ingredientRepository = ingredientRepository; + } + + public Optional findById(Long id) { + return ingredientRepository.findById(id); + } + + public List findAll() { + return ingredientRepository.findAll(); + } + + public List findAll(int limit) { + return ingredientRepository.findAll(PageRequest.of(0, limit)).toList(); + } + + /** + * Creates a new ingredient. Returns empty if the recipe with the same name or id already exists. + * @param ingredient Ingredient to be saved in the db. + * @return The created ingredient (the ingredient arg with a new assigned id) or empty if it already exists in db. + */ + public Optional create(Ingredient ingredient) { + if (ingredientRepository.existsByName(ingredient.getName()) || + ingredientRepository.existsById(ingredient.getId())) { + return Optional.empty(); + } + + return Optional.of(ingredientRepository.save(ingredient)); + } + + /** + * Updates an ingredient. The ingredient with the provided id will be replaced (in db) with the provided ingredient. + * @param id id of the ingredient to update. + * @param ingredient Ingredient to be saved in the db. + * @return The created ingredient (the ingredient arg with a new assigned id.) + */ + public Optional update(Long id, Ingredient ingredient) { + assert id.equals(ingredient.getId()) : + "The id of the updated ingredient doesn't match the provided ingredient's id."; + if (!ingredientRepository.existsById(id)) { + return Optional.empty(); + } + + return Optional.of(ingredientRepository.save(ingredient)); + } + + public void delete(Long id) { + ingredientRepository.deleteById(id); + } + +} From 00506719443b24cfe1c763a311375046149e6931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Rasie=C5=84ski?= Date: Thu, 8 Jan 2026 01:04:05 +0100 Subject: [PATCH 5/9] Moved services --- .../main/java/{ => server}/service/IngredientService.java | 2 +- .../src/main/java/{ => server}/service/RecipeService.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) rename server/src/main/java/{ => server}/service/IngredientService.java (98%) rename server/src/main/java/{ => server}/service/RecipeService.java (95%) diff --git a/server/src/main/java/service/IngredientService.java b/server/src/main/java/server/service/IngredientService.java similarity index 98% rename from server/src/main/java/service/IngredientService.java rename to server/src/main/java/server/service/IngredientService.java index a519107..4edcb88 100644 --- a/server/src/main/java/service/IngredientService.java +++ b/server/src/main/java/server/service/IngredientService.java @@ -1,4 +1,4 @@ -package service; +package server.service; import commons.Ingredient; import org.springframework.data.domain.PageRequest; diff --git a/server/src/main/java/service/RecipeService.java b/server/src/main/java/server/service/RecipeService.java similarity index 95% rename from server/src/main/java/service/RecipeService.java rename to server/src/main/java/server/service/RecipeService.java index 1c0ea4e..ac38e3c 100644 --- a/server/src/main/java/service/RecipeService.java +++ b/server/src/main/java/server/service/RecipeService.java @@ -1,4 +1,4 @@ -package service; +package server.service; import commons.Recipe; import org.springframework.data.domain.PageRequest; @@ -65,9 +65,11 @@ public class RecipeService { return Optional.of(saveWithDependencies(recipe)); } - public void delete(Long id) { + public boolean delete(Long id) { // TODO: Propagate deletion to ingredients. + if (!recipeRepository.existsById(id)) return false; recipeRepository.deleteById(id); + return true; } private Recipe saveWithDependencies(Recipe recipe) { From e9b6d81a27c00367a536a7021918a57778d9f549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Rasie=C5=84ski?= Date: Thu, 8 Jan 2026 01:05:36 +0100 Subject: [PATCH 6/9] Refactored recipe controller to use services --- .../java/server/api/RecipeController.java | 94 +++++-------------- .../java/server/api/RecipeControllerTest.java | 26 ++--- 2 files changed, 36 insertions(+), 84 deletions(-) diff --git a/server/src/main/java/server/api/RecipeController.java b/server/src/main/java/server/api/RecipeController.java index 2a56310..37a2a78 100644 --- a/server/src/main/java/server/api/RecipeController.java +++ b/server/src/main/java/server/api/RecipeController.java @@ -7,8 +7,6 @@ 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; @@ -22,9 +20,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import server.database.IngredientRepository; -import server.database.RecipeIngredientRepository; -import server.database.RecipeRepository; +import server.service.RecipeService; import java.util.List; import java.util.Optional; @@ -32,19 +28,12 @@ import java.util.Optional; @RestController @RequestMapping("/api") public class RecipeController { - private final RecipeRepository recipeRepository; // JPA repository used in this controller private final SimpMessagingTemplate messagingTemplate; - private final RecipeIngredientRepository recipeIngredientRepository; - private final IngredientRepository ingredientRepository; + private final RecipeService recipeService; - public RecipeController(RecipeRepository recipeRepository, - SimpMessagingTemplate messagingTemplate, - IngredientRepository ingredientRepository, - RecipeIngredientRepository recipeIngredientRepository) { - this.recipeRepository = recipeRepository; + public RecipeController(RecipeService recipeService, SimpMessagingTemplate messagingTemplate) { + this.recipeService = recipeService; this.messagingTemplate = messagingTemplate; - this.recipeIngredientRepository = recipeIngredientRepository; - this.ingredientRepository = ingredientRepository; } /** @@ -57,10 +46,9 @@ public class RecipeController { */ @GetMapping("/recipe/{id}") public ResponseEntity getRecipe(@PathVariable Long id) { - if (!recipeRepository.existsById(id)) { - return ResponseEntity.notFound().build(); - } - return ResponseEntity.ok(recipeRepository.findById(id).get()); + return recipeService.findById(id) + .map(ResponseEntity::ok) + .orElseGet(() -> ResponseEntity.notFound().build()); } /** @@ -72,28 +60,12 @@ public class RecipeController { */ @GetMapping("/recipes") public ResponseEntity> getRecipes(@RequestParam Optional limit) { - if (limit.isPresent()) { - return ResponseEntity.ok( - recipeRepository.findAll( - PageRequest.of(0, limit.get()) - ).toList()); - } + return ResponseEntity.ok( + // Choose the right overload. One has a limit, other doesn't. + limit.map(recipeService::findAll).orElseGet(recipeService::findAll) + ); + } - return ResponseEntity.ok(recipeRepository.findAll()); - } - private Recipe saveRecipeAndDependencies(Recipe recipe) { - recipe.getIngredients() - .forEach(recipeIngredient -> - recipeIngredient.setIngredient( - ingredientRepository - .findByName(recipeIngredient.getIngredient().name) - .orElseGet(() -> ingredientRepository.save(recipeIngredient.getIngredient()) - )) - ); - recipeIngredientRepository.saveAll(recipe.getIngredients()); - Recipe saved = recipeRepository.save(recipe); - return saved; - } /** * Mapping for POST /recipe/{id}. * Also creates the ingredient elements if they do not exist. @@ -104,13 +76,12 @@ public class RecipeController { */ @PostMapping("/recipe/{id}") public ResponseEntity updateRecipe(@PathVariable Long id, @RequestBody Recipe recipe) { - if (!recipeRepository.existsById(id)) { - return ResponseEntity.badRequest().build(); - } - Recipe saved = saveRecipeAndDependencies(recipe); - messagingTemplate.convertAndSend(Topics.RECIPES, new UpdateRecipeMessage(saved)); - - return ResponseEntity.ok(saved); + return recipeService.update(id, recipe) + .map(saved -> { + messagingTemplate.convertAndSend(Topics.RECIPES, new UpdateRecipeMessage(saved)); // Send to WS. + return ResponseEntity.ok(saved); + }) + .orElseGet(() -> ResponseEntity.notFound().build()); // Recipe with that id not found. } /** @@ -125,22 +96,12 @@ public class RecipeController { */ @PutMapping("/recipe/new") public ResponseEntity createRecipe(@RequestBody Recipe recipe) { - - // We initialize a new example recipe with the name of input recipe - // This is the only attribute we are concerned about making sure it's unique - Recipe example = new Recipe(); - example.setName(recipe.getName()); - - /* Here we use very funny JPA magic repository.exists(Example) - We check if any recipe in the repository has the same name as the input - */ - if (recipeRepository.exists(Example.of(example))) { - return ResponseEntity.badRequest().build(); - } - Recipe saved = saveRecipeAndDependencies(recipe); - messagingTemplate.convertAndSend(Topics.RECIPES, new CreateRecipeMessage(saved)); - - return ResponseEntity.ok(saved); + return recipeService.create(recipe) + .map(saved -> { + messagingTemplate.convertAndSend(Topics.RECIPES, new CreateRecipeMessage(saved)); // Send to WS. + return ResponseEntity.ok(saved); + }) + .orElseGet(() -> ResponseEntity.badRequest().build()); // That recipe already exists. } /** @@ -153,13 +114,10 @@ public class RecipeController { */ @DeleteMapping("/recipe/{id}") public ResponseEntity deleteRecipe(@PathVariable Long id) { - if (!recipeRepository.existsById(id)) { + if (!recipeService.delete(id)) { return ResponseEntity.badRequest().build(); } - recipeRepository.deleteById(id); - - messagingTemplate.convertAndSend(Topics.RECIPES, new DeleteRecipeMessage(id)); - + messagingTemplate.convertAndSend(Topics.RECIPES, new DeleteRecipeMessage(id)); // Send to WS. return ResponseEntity.ok(true); } } diff --git a/server/src/test/java/server/api/RecipeControllerTest.java b/server/src/test/java/server/api/RecipeControllerTest.java index c16490c..c052688 100644 --- a/server/src/test/java/server/api/RecipeControllerTest.java +++ b/server/src/test/java/server/api/RecipeControllerTest.java @@ -13,9 +13,8 @@ import org.springframework.http.HttpStatus; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.test.context.ActiveProfiles; import server.WebSocketConfig; -import server.database.IngredientRepository; -import server.database.RecipeIngredientRepository; import server.database.RecipeRepository; +import server.service.RecipeService; import java.util.ArrayList; import java.util.List; @@ -38,30 +37,27 @@ import static org.junit.jupiter.api.Assertions.assertEquals; // This is required to enable WebSocket messaging in tests // // Without this line, Spring screams about missing SimpMessagingTemplate bean -@Import(WebSocketConfig.class) +@Import({WebSocketConfig.class, RecipeService.class}) public class RecipeControllerTest { - + private final RecipeService recipeService; + private final RecipeRepository recipeRepository; private final SimpMessagingTemplate template; private RecipeController controller; + private List recipes; - private final RecipeRepository recipeRepository; private List recipeIds; public static final int NUM_RECIPES = 10; - private final IngredientRepository ingredientRepository; - private final RecipeIngredientRepository recipeIngredientRepository; // Injects a test repository into the test class @Autowired public RecipeControllerTest( + RecipeService recipeService, RecipeRepository recipeRepository, - SimpMessagingTemplate template, - IngredientRepository ingredientRepository, - RecipeIngredientRepository recipeIngredientRepository + SimpMessagingTemplate template ) { + this.recipeService = recipeService; this.recipeRepository = recipeRepository; this.template = template; - this.ingredientRepository = ingredientRepository; - this.recipeIngredientRepository = recipeIngredientRepository; } @BeforeEach @@ -71,10 +67,8 @@ public class RecipeControllerTest { .mapToObj(x -> new Recipe(null, "Recipe " + x, List.of(), List.of())) .toList(); controller = new RecipeController( - recipeRepository, - template, - ingredientRepository, - recipeIngredientRepository + recipeService, + template ); Set tags = info.getTags(); List ids = new ArrayList<>(); From 707f88b70b58a52f300f6c425541d0ea418c379f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Rasie=C5=84ski?= Date: Thu, 8 Jan 2026 01:43:18 +0100 Subject: [PATCH 7/9] Fixed ordering in ingredient service. --- .../main/java/server/service/IngredientService.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/server/service/IngredientService.java b/server/src/main/java/server/service/IngredientService.java index 4edcb88..8a79659 100644 --- a/server/src/main/java/server/service/IngredientService.java +++ b/server/src/main/java/server/service/IngredientService.java @@ -21,11 +21,11 @@ public class IngredientService { } public List findAll() { - return ingredientRepository.findAll(); + return ingredientRepository.findAllByOrderByNameAsc(); } - public List findAll(int limit) { - return ingredientRepository.findAll(PageRequest.of(0, limit)).toList(); + public List findAll(int page, int limit) { + return ingredientRepository.findAllByOrderByNameAsc(PageRequest.of(page, limit)).toList(); } /** @@ -58,8 +58,10 @@ public class IngredientService { return Optional.of(ingredientRepository.save(ingredient)); } - public void delete(Long id) { + public boolean delete(Long id) { + if (!ingredientRepository.existsById(id)) return false; ingredientRepository.deleteById(id); + return true; } } From 04f58c22cc9ebd5313e0f70daeacb257ed8d9f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Rasie=C5=84ski?= Date: Thu, 8 Jan 2026 01:43:56 +0100 Subject: [PATCH 8/9] Refactored IngredientController to use services. --- .../java/server/api/IngredientController.java | 58 +++++++------------ .../server/api/IngredientControllerTest.java | 8 ++- 2 files changed, 27 insertions(+), 39 deletions(-) diff --git a/server/src/main/java/server/api/IngredientController.java b/server/src/main/java/server/api/IngredientController.java index 946a62d..324276b 100644 --- a/server/src/main/java/server/api/IngredientController.java +++ b/server/src/main/java/server/api/IngredientController.java @@ -5,8 +5,6 @@ import commons.ws.Topics; import commons.ws.messages.CreateIngredientMessage; import commons.ws.messages.DeleteIngredientMessage; import commons.ws.messages.UpdateIngredientMessage; -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; @@ -19,6 +17,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import server.database.IngredientRepository; +import server.service.IngredientService; import java.util.Optional; import java.util.List; @@ -42,12 +41,12 @@ import java.util.List; @RestController @RequestMapping("/api") public class IngredientController { - private final IngredientRepository ingredientRepository; + private final IngredientService ingredientService; private final SimpMessagingTemplate messagingTemplate; - public IngredientController(IngredientRepository ingredientRepository, + public IngredientController(IngredientService ingredientService, SimpMessagingTemplate messagingTemplate) { - this.ingredientRepository = ingredientRepository; + this.ingredientService = ingredientService; this.messagingTemplate = messagingTemplate; } @@ -75,15 +74,9 @@ public class IngredientController { @RequestParam Optional page, @RequestParam Optional limit ) { - List ingredients = limit - .map(l -> { - return ingredientRepository.findAllByOrderByNameAsc( - PageRequest.of(page.orElse(0), l) - ).toList(); - }) - .orElseGet(ingredientRepository::findAllByOrderByNameAsc); - - return ResponseEntity.ok(ingredients); + return limit + .map(integer -> ResponseEntity.ok(ingredientService.findAll(page.orElse(0), integer))) + .orElseGet(() -> ResponseEntity.ok(ingredientService.findAll())); } /** @@ -102,7 +95,7 @@ public class IngredientController { */ @GetMapping("/ingredients/{id}") public ResponseEntity getIngredientById(@PathVariable Long id) { - return ingredientRepository.findById(id) + return ingredientService.findById(id) .map(ResponseEntity::ok) .orElseGet(() -> ResponseEntity.notFound().build()); } @@ -130,15 +123,13 @@ public class IngredientController { @PathVariable Long id, @RequestBody Ingredient updated ) { - if (!ingredientRepository.existsById(id)) { - return ResponseEntity.notFound().build(); - } - updated.setId(id); - Ingredient savedIngredient = ingredientRepository.save(updated); - messagingTemplate.convertAndSend(Topics.INGREDIENTS, new CreateIngredientMessage(savedIngredient)); - - return ResponseEntity.ok(savedIngredient); + return ingredientService.update(id, updated) + .map(saved -> { + messagingTemplate.convertAndSend(Topics.INGREDIENTS, new CreateIngredientMessage(saved)); + return ResponseEntity.ok(saved); + }) + .orElseGet(() -> ResponseEntity.notFound().build()); } /** @@ -164,17 +155,12 @@ public class IngredientController { return ResponseEntity.badRequest().build(); } - Ingredient example = new Ingredient(); - example.name = ingredient.name; - - if (ingredientRepository.existsById(ingredient.id) || ingredientRepository.exists(Example.of(example))) { - return ResponseEntity.badRequest().build(); - } - - Ingredient saved = ingredientRepository.save(ingredient); - messagingTemplate.convertAndSend(Topics.INGREDIENTS, new UpdateIngredientMessage(saved)); - - return ResponseEntity.ok(saved); + return ingredientService.create(ingredient) + .map(saved -> { + messagingTemplate.convertAndSend(Topics.INGREDIENTS, new UpdateIngredientMessage(saved)); + return ResponseEntity.ok(saved); + }) + .orElseGet(() -> ResponseEntity.badRequest().build()); } /** @@ -193,13 +179,11 @@ public class IngredientController { */ @DeleteMapping("/ingredients/{id}") public ResponseEntity deleteIngredient(@PathVariable Long id) { - if (!ingredientRepository.existsById(id)) { + if (!ingredientService.delete(id)) { return ResponseEntity.notFound().build(); } - ingredientRepository.deleteById(id); messagingTemplate.convertAndSend(Topics.INGREDIENTS, new DeleteIngredientMessage(id)); - return ResponseEntity.ok(true); } } diff --git a/server/src/test/java/server/api/IngredientControllerTest.java b/server/src/test/java/server/api/IngredientControllerTest.java index 57523b9..849269a 100644 --- a/server/src/test/java/server/api/IngredientControllerTest.java +++ b/server/src/test/java/server/api/IngredientControllerTest.java @@ -11,6 +11,7 @@ import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.test.context.ActiveProfiles; import server.database.IngredientRepository; import server.WebSocketConfig; +import server.service.IngredientService; import static org.junit.jupiter.api.Assertions.*; @@ -20,10 +21,11 @@ import java.util.stream.Stream; @DataJpaTest @ActiveProfiles("mock-data-test") -@Import(WebSocketConfig.class) +@Import({WebSocketConfig.class, IngredientService.class}) public class IngredientControllerTest { private final SimpMessagingTemplate template; private final IngredientRepository ingredientRepository; + private final IngredientService ingredientService; private IngredientController controller; private static final double PROTEIN_BASE = 1.0; @@ -42,8 +44,10 @@ public class IngredientControllerTest { @Autowired public IngredientControllerTest(IngredientRepository ingredientRepository, + IngredientService ingredientService, SimpMessagingTemplate template) { this.ingredientRepository = ingredientRepository; + this.ingredientService = ingredientService; this.template = template; } @@ -59,7 +63,7 @@ public class IngredientControllerTest { @BeforeEach public void setup() { - controller = new IngredientController(ingredientRepository, template); + controller = new IngredientController(ingredientService, template); this.createInitialIngredients(); } From 64dd5e4a281b0bf7bb4deb5314caf6bcfc57f5e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Rasie=C5=84ski?= Date: Thu, 8 Jan 2026 01:49:21 +0100 Subject: [PATCH 9/9] Changed SomeController to be a health check --- .../HealthCheckController.java} | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) rename server/src/main/java/server/{SomeController.java => api/HealthCheckController.java} (61%) diff --git a/server/src/main/java/server/SomeController.java b/server/src/main/java/server/api/HealthCheckController.java similarity index 61% rename from server/src/main/java/server/SomeController.java rename to server/src/main/java/server/api/HealthCheckController.java index 3e0b88c..734b633 100644 --- a/server/src/main/java/server/SomeController.java +++ b/server/src/main/java/server/api/HealthCheckController.java @@ -1,17 +1,16 @@ -package server; +package server.api; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; -@Controller +@RestController @RequestMapping("/") -public class SomeController { - +public class HealthCheckController { @GetMapping("/") @ResponseBody public String index() { - return "Hello world!"; + return "Server is online!"; } } \ No newline at end of file