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.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<Recipe> 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<List<Recipe>> getRecipes(@RequestParam Optional<Integer> 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 <code>POST /recipe/{id}</code>.
|
||||
* Also creates the ingredient elements if they do not exist.
|
||||
|
|
@ -104,13 +76,12 @@ public class RecipeController {
|
|||
*/
|
||||
@PostMapping("/recipe/{id}")
|
||||
public ResponseEntity<Recipe> 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<Recipe> 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<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);
|
||||
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<Boolean> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Recipe> recipes;
|
||||
private final RecipeRepository recipeRepository;
|
||||
private List<Long> 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<String> tags = info.getTags();
|
||||
List<Long> ids = new ArrayList<>();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue