Refactored recipe controller to use services
This commit is contained in:
parent
0050671944
commit
e9b6d81a27
2 changed files with 36 additions and 84 deletions
|
|
@ -7,8 +7,6 @@ import commons.ws.Topics;
|
||||||
import commons.ws.messages.CreateRecipeMessage;
|
import commons.ws.messages.CreateRecipeMessage;
|
||||||
import commons.ws.messages.DeleteRecipeMessage;
|
import commons.ws.messages.DeleteRecipeMessage;
|
||||||
import commons.ws.messages.UpdateRecipeMessage;
|
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.http.ResponseEntity;
|
||||||
|
|
||||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
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.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import server.database.IngredientRepository;
|
import server.service.RecipeService;
|
||||||
import server.database.RecipeIngredientRepository;
|
|
||||||
import server.database.RecipeRepository;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
@ -32,19 +28,12 @@ import java.util.Optional;
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api")
|
@RequestMapping("/api")
|
||||||
public class RecipeController {
|
public class RecipeController {
|
||||||
private final RecipeRepository recipeRepository; // JPA repository used in this controller
|
|
||||||
private final SimpMessagingTemplate messagingTemplate;
|
private final SimpMessagingTemplate messagingTemplate;
|
||||||
private final RecipeIngredientRepository recipeIngredientRepository;
|
private final RecipeService recipeService;
|
||||||
private final IngredientRepository ingredientRepository;
|
|
||||||
|
|
||||||
public RecipeController(RecipeRepository recipeRepository,
|
public RecipeController(RecipeService recipeService, SimpMessagingTemplate messagingTemplate) {
|
||||||
SimpMessagingTemplate messagingTemplate,
|
this.recipeService = recipeService;
|
||||||
IngredientRepository ingredientRepository,
|
|
||||||
RecipeIngredientRepository recipeIngredientRepository) {
|
|
||||||
this.recipeRepository = recipeRepository;
|
|
||||||
this.messagingTemplate = messagingTemplate;
|
this.messagingTemplate = messagingTemplate;
|
||||||
this.recipeIngredientRepository = recipeIngredientRepository;
|
|
||||||
this.ingredientRepository = ingredientRepository;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -57,10 +46,9 @@ public class RecipeController {
|
||||||
*/
|
*/
|
||||||
@GetMapping("/recipe/{id}")
|
@GetMapping("/recipe/{id}")
|
||||||
public ResponseEntity<Recipe> getRecipe(@PathVariable Long id) {
|
public ResponseEntity<Recipe> getRecipe(@PathVariable Long id) {
|
||||||
if (!recipeRepository.existsById(id)) {
|
return recipeService.findById(id)
|
||||||
return ResponseEntity.notFound().build();
|
.map(ResponseEntity::ok)
|
||||||
}
|
.orElseGet(() -> ResponseEntity.notFound().build());
|
||||||
return ResponseEntity.ok(recipeRepository.findById(id).get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -72,28 +60,12 @@ public class RecipeController {
|
||||||
*/
|
*/
|
||||||
@GetMapping("/recipes")
|
@GetMapping("/recipes")
|
||||||
public ResponseEntity<List<Recipe>> getRecipes(@RequestParam Optional<Integer> limit) {
|
public ResponseEntity<List<Recipe>> getRecipes(@RequestParam Optional<Integer> limit) {
|
||||||
if (limit.isPresent()) {
|
return ResponseEntity.ok(
|
||||||
return ResponseEntity.ok(
|
// Choose the right overload. One has a limit, other doesn't.
|
||||||
recipeRepository.findAll(
|
limit.map(recipeService::findAll).orElseGet(recipeService::findAll)
|
||||||
PageRequest.of(0, limit.get())
|
);
|
||||||
).toList());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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 <code>POST /recipe/{id}</code>.
|
* Mapping for <code>POST /recipe/{id}</code>.
|
||||||
* Also creates the ingredient elements if they do not exist.
|
* Also creates the ingredient elements if they do not exist.
|
||||||
|
|
@ -104,13 +76,12 @@ public class RecipeController {
|
||||||
*/
|
*/
|
||||||
@PostMapping("/recipe/{id}")
|
@PostMapping("/recipe/{id}")
|
||||||
public ResponseEntity<Recipe> updateRecipe(@PathVariable Long id, @RequestBody Recipe recipe) {
|
public ResponseEntity<Recipe> updateRecipe(@PathVariable Long id, @RequestBody Recipe recipe) {
|
||||||
if (!recipeRepository.existsById(id)) {
|
return recipeService.update(id, recipe)
|
||||||
return ResponseEntity.badRequest().build();
|
.map(saved -> {
|
||||||
}
|
messagingTemplate.convertAndSend(Topics.RECIPES, new UpdateRecipeMessage(saved)); // Send to WS.
|
||||||
Recipe saved = saveRecipeAndDependencies(recipe);
|
return ResponseEntity.ok(saved);
|
||||||
messagingTemplate.convertAndSend(Topics.RECIPES, new UpdateRecipeMessage(saved));
|
})
|
||||||
|
.orElseGet(() -> ResponseEntity.notFound().build()); // Recipe with that id not found.
|
||||||
return ResponseEntity.ok(saved);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -125,22 +96,12 @@ public class RecipeController {
|
||||||
*/
|
*/
|
||||||
@PutMapping("/recipe/new")
|
@PutMapping("/recipe/new")
|
||||||
public ResponseEntity<Recipe> createRecipe(@RequestBody Recipe recipe) {
|
public ResponseEntity<Recipe> createRecipe(@RequestBody Recipe recipe) {
|
||||||
|
return recipeService.create(recipe)
|
||||||
// We initialize a new example recipe with the name of input recipe
|
.map(saved -> {
|
||||||
// This is the only attribute we are concerned about making sure it's unique
|
messagingTemplate.convertAndSend(Topics.RECIPES, new CreateRecipeMessage(saved)); // Send to WS.
|
||||||
Recipe example = new Recipe();
|
return ResponseEntity.ok(saved);
|
||||||
example.setName(recipe.getName());
|
})
|
||||||
|
.orElseGet(() -> ResponseEntity.badRequest().build()); // That recipe already exists.
|
||||||
/* Here we use very funny JPA magic repository.exists(Example<Recipe>)
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -153,13 +114,10 @@ public class RecipeController {
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/recipe/{id}")
|
@DeleteMapping("/recipe/{id}")
|
||||||
public ResponseEntity<Boolean> deleteRecipe(@PathVariable Long id) {
|
public ResponseEntity<Boolean> deleteRecipe(@PathVariable Long id) {
|
||||||
if (!recipeRepository.existsById(id)) {
|
if (!recipeService.delete(id)) {
|
||||||
return ResponseEntity.badRequest().build();
|
return ResponseEntity.badRequest().build();
|
||||||
}
|
}
|
||||||
recipeRepository.deleteById(id);
|
messagingTemplate.convertAndSend(Topics.RECIPES, new DeleteRecipeMessage(id)); // Send to WS.
|
||||||
|
|
||||||
messagingTemplate.convertAndSend(Topics.RECIPES, new DeleteRecipeMessage(id));
|
|
||||||
|
|
||||||
return ResponseEntity.ok(true);
|
return ResponseEntity.ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,8 @@ import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||||
import org.springframework.test.context.ActiveProfiles;
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
import server.WebSocketConfig;
|
import server.WebSocketConfig;
|
||||||
import server.database.IngredientRepository;
|
|
||||||
import server.database.RecipeIngredientRepository;
|
|
||||||
import server.database.RecipeRepository;
|
import server.database.RecipeRepository;
|
||||||
|
import server.service.RecipeService;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
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
|
// This is required to enable WebSocket messaging in tests
|
||||||
//
|
//
|
||||||
// Without this line, Spring screams about missing SimpMessagingTemplate bean
|
// Without this line, Spring screams about missing SimpMessagingTemplate bean
|
||||||
@Import(WebSocketConfig.class)
|
@Import({WebSocketConfig.class, RecipeService.class})
|
||||||
public class RecipeControllerTest {
|
public class RecipeControllerTest {
|
||||||
|
private final RecipeService recipeService;
|
||||||
|
private final RecipeRepository recipeRepository;
|
||||||
private final SimpMessagingTemplate template;
|
private final SimpMessagingTemplate template;
|
||||||
private RecipeController controller;
|
private RecipeController controller;
|
||||||
|
|
||||||
private List<Recipe> recipes;
|
private List<Recipe> recipes;
|
||||||
private final RecipeRepository recipeRepository;
|
|
||||||
private List<Long> recipeIds;
|
private List<Long> recipeIds;
|
||||||
public static final int NUM_RECIPES = 10;
|
public static final int NUM_RECIPES = 10;
|
||||||
private final IngredientRepository ingredientRepository;
|
|
||||||
private final RecipeIngredientRepository recipeIngredientRepository;
|
|
||||||
|
|
||||||
// Injects a test repository into the test class
|
// Injects a test repository into the test class
|
||||||
@Autowired
|
@Autowired
|
||||||
public RecipeControllerTest(
|
public RecipeControllerTest(
|
||||||
|
RecipeService recipeService,
|
||||||
RecipeRepository recipeRepository,
|
RecipeRepository recipeRepository,
|
||||||
SimpMessagingTemplate template,
|
SimpMessagingTemplate template
|
||||||
IngredientRepository ingredientRepository,
|
|
||||||
RecipeIngredientRepository recipeIngredientRepository
|
|
||||||
) {
|
) {
|
||||||
|
this.recipeService = recipeService;
|
||||||
this.recipeRepository = recipeRepository;
|
this.recipeRepository = recipeRepository;
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.ingredientRepository = ingredientRepository;
|
|
||||||
this.recipeIngredientRepository = recipeIngredientRepository;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
|
@ -71,10 +67,8 @@ public class RecipeControllerTest {
|
||||||
.mapToObj(x -> new Recipe(null, "Recipe " + x, List.of(), List.of()))
|
.mapToObj(x -> new Recipe(null, "Recipe " + x, List.of(), List.of()))
|
||||||
.toList();
|
.toList();
|
||||||
controller = new RecipeController(
|
controller = new RecipeController(
|
||||||
recipeRepository,
|
recipeService,
|
||||||
template,
|
template
|
||||||
ingredientRepository,
|
|
||||||
recipeIngredientRepository
|
|
||||||
);
|
);
|
||||||
Set<String> tags = info.getTags();
|
Set<String> tags = info.getTags();
|
||||||
List<Long> ids = new ArrayList<>();
|
List<Long> ids = new ArrayList<>();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue