Skip to content

Commit 9c3df98

Browse files
committed
Using Setters for JPA Bidirectional Relationships
(main idea is clean code & making things at one place instead of doing them here and there). -hulet gize andun landu assign kemareg, andun set senareg bezagnaw side yalewn erasu set endiareg mareg. -some entity pass mideregewn erasu endiareg bemareg egna pass mareg endaynorben mareg. -in many side gena getthe set/list blen gena add kemenel esu bewust awakinet biyaregew ... egna add mareg mnfelgewn object melak bcha new mitebekbn.
1 parent 0802c61 commit 9c3df98

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1909
-424
lines changed

pom.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@
4848
<artifactId>h2</artifactId>
4949
<scope>runtime</scope>
5050
</dependency>
51+
<dependency>
52+
<groupId>org.projectlombok</groupId>
53+
<artifactId>lombok</artifactId>
54+
<!-- not version b/c projectlombok is supported by the curated dependenciesof the spring boot starter-->
55+
</dependency>
56+
<dependency>
57+
<groupId>org.webjars</groupId>
58+
<artifactId>bootstrap</artifactId>
59+
<version>3.3.7-1</version>
60+
</dependency>
61+
<dependency>
62+
<groupId>org.webjars</groupId>
63+
<artifactId>jquery</artifactId>
64+
<version>3.2.1</version>
65+
</dependency>
5166
<dependency>
5267
<groupId>org.springframework.boot</groupId>
5368
<artifactId>spring-boot-starter-test</artifactId>

src/main/java/guru/springframework/bootstrap/RecipeBootstrap.java

Lines changed: 81 additions & 77 deletions
Large diffs are not rendered by default.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package guru.springframework.commands;
2+
3+
import lombok.Getter;
4+
import lombok.NoArgsConstructor;
5+
import lombok.Setter;
6+
7+
@Setter
8+
@Getter
9+
@NoArgsConstructor
10+
public class CategoryCommand {
11+
private Long id;
12+
private String description;
13+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package guru.springframework.commands;
2+
3+
import lombok.Getter;
4+
import lombok.NoArgsConstructor;
5+
import lombok.Setter;
6+
7+
import java.math.BigDecimal;
8+
9+
@Setter
10+
@Getter
11+
@NoArgsConstructor
12+
public class IngredientCommand {
13+
private Long id;
14+
private Long recipeId;
15+
private String description;
16+
private BigDecimal amount;
17+
private UnitOfMeasureCommand uom;
18+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package guru.springframework.commands;
2+
3+
import lombok.Getter;
4+
import lombok.NoArgsConstructor;
5+
import lombok.Setter;
6+
7+
@Setter
8+
@Getter
9+
@NoArgsConstructor
10+
public class NotesCommand {
11+
private Long id;
12+
private String recipeNotes;
13+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package guru.springframework.commands;
2+
3+
4+
import guru.springframework.domain.Difficulty;
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
import lombok.Setter;
8+
9+
import java.util.HashSet;
10+
import java.util.Set;
11+
12+
@Getter
13+
@Setter
14+
@NoArgsConstructor
15+
public class RecipeCommand {
16+
private Long id;
17+
private String description;
18+
private Integer prepTime;
19+
private Integer cookTime;
20+
private Integer servings;
21+
private String source;
22+
private String url;
23+
private String directions;
24+
private Set<IngredientCommand> ingredients = new HashSet<>();
25+
private Byte[] image;
26+
private Difficulty difficulty;
27+
private NotesCommand notes;
28+
private Set<CategoryCommand> categories = new HashSet<>();
29+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package guru.springframework.commands;
2+
3+
import lombok.Getter;
4+
import lombok.NoArgsConstructor;
5+
import lombok.Setter;
6+
7+
@Setter
8+
@Getter
9+
@NoArgsConstructor
10+
public class UnitOfMeasureCommand {
11+
private Long id;
12+
private String description;
13+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package guru.springframework.controllers;
2+
3+
import guru.springframework.commands.RecipeCommand;
4+
import guru.springframework.services.ImageService;
5+
import guru.springframework.services.RecipeService;
6+
import org.apache.tomcat.util.http.fileupload.IOUtils;
7+
import org.springframework.stereotype.Controller;
8+
import org.springframework.ui.Model;
9+
import org.springframework.web.bind.annotation.GetMapping;
10+
import org.springframework.web.bind.annotation.PathVariable;
11+
import org.springframework.web.bind.annotation.PostMapping;
12+
import org.springframework.web.bind.annotation.RequestParam;
13+
import org.springframework.web.multipart.MultipartFile;
14+
15+
import javax.servlet.http.HttpServletResponse;
16+
import java.io.ByteArrayInputStream;
17+
import java.io.IOException;
18+
import java.io.InputStream;
19+
20+
/**
21+
* Created by jt on 7/3/17.
22+
*/
23+
@Controller
24+
public class ImageController {
25+
26+
private final ImageService imageService;
27+
private final RecipeService recipeService;
28+
29+
public ImageController(ImageService imageService, RecipeService recipeService) {
30+
this.imageService = imageService;
31+
this.recipeService = recipeService;
32+
}
33+
34+
@GetMapping("recipe/{id}/image")
35+
public String showUploadForm(@PathVariable String id, Model model){
36+
model.addAttribute("recipe", recipeService.findCommandById(Long.valueOf(id)));
37+
38+
return "recipe/imageuploadform";
39+
}
40+
41+
@PostMapping("recipe/{id}/image")
42+
public String handleImagePost(@PathVariable String id, @RequestParam("imagefile") MultipartFile file){
43+
44+
imageService.saveImageFile(Long.valueOf(id), file);
45+
46+
return "redirect:/recipe/" + id + "/show";
47+
}
48+
49+
@GetMapping("recipe/{id}/recipeimage")
50+
public void renderImageFromDB(@PathVariable String id, HttpServletResponse response) throws IOException {
51+
RecipeCommand recipeCommand = recipeService.findCommandById(Long.valueOf(id));
52+
53+
if (recipeCommand.getImage() != null) {
54+
byte[] byteArray = new byte[recipeCommand.getImage().length];
55+
int i = 0;
56+
57+
for (Byte wrappedByte : recipeCommand.getImage()){
58+
byteArray[i++] = wrappedByte; //auto unboxing
59+
}
60+
61+
response.setContentType("image/jpeg");
62+
InputStream is = new ByteArrayInputStream(byteArray);
63+
IOUtils.copy(is, response.getOutputStream());
64+
}
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,30 @@
11
package guru.springframework.controllers;
22

33
import guru.springframework.services.RecipeService;
4+
import lombok.extern.slf4j.Slf4j;
45
import org.springframework.stereotype.Controller;
56
import org.springframework.ui.Model;
67
import org.springframework.web.bind.annotation.RequestMapping;
78

9+
/**
10+
* Created by jt on 6/1/17.
11+
*/
12+
@Slf4j
813
@Controller
9-
public class IndexContoller {
14+
public class IndexController {
1015

1116
private final RecipeService recipeService;
1217

13-
public IndexContoller(RecipeService recipeService) {
18+
public IndexController(RecipeService recipeService) {
1419
this.recipeService = recipeService;
1520
}
16-
@RequestMapping({"","/","/index"})
21+
22+
@RequestMapping({"", "/", "/index"})
1723
public String getIndexPage(Model model) {
24+
log.debug("Getting Index page");
1825

19-
model.addAttribute("recipes", recipeService.getRecipe());
26+
model.addAttribute("recipes", recipeService.getRecipes());
2027

2128
return "index";
2229
}
23-
}
30+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package guru.springframework.controllers;
2+
3+
import guru.springframework.commands.IngredientCommand;
4+
import guru.springframework.commands.RecipeCommand;
5+
import guru.springframework.commands.UnitOfMeasureCommand;
6+
import guru.springframework.services.IngredientService;
7+
import guru.springframework.services.RecipeService;
8+
import guru.springframework.services.UnitOfMeasureService;
9+
import lombok.extern.slf4j.Slf4j;
10+
import org.springframework.stereotype.Controller;
11+
import org.springframework.ui.Model;
12+
import org.springframework.web.bind.annotation.GetMapping;
13+
import org.springframework.web.bind.annotation.ModelAttribute;
14+
import org.springframework.web.bind.annotation.PathVariable;
15+
import org.springframework.web.bind.annotation.PostMapping;
16+
17+
/**
18+
* Created by jt on 6/28/17.
19+
*/
20+
@Slf4j
21+
@Controller
22+
public class IngredientController {
23+
24+
private final IngredientService ingredientService;
25+
private final RecipeService recipeService;
26+
private final UnitOfMeasureService unitOfMeasureService;
27+
28+
public IngredientController(IngredientService ingredientService, RecipeService recipeService, UnitOfMeasureService unitOfMeasureService) {
29+
this.ingredientService = ingredientService;
30+
this.recipeService = recipeService;
31+
this.unitOfMeasureService = unitOfMeasureService;
32+
}
33+
34+
@GetMapping("/recipe/{recipeId}/ingredients")
35+
public String listIngredients(@PathVariable String recipeId, Model model){
36+
log.debug("Getting ingredient list for recipe id: " + recipeId);
37+
38+
// use command object to avoid lazy load errors in Thymeleaf.
39+
model.addAttribute("recipe", recipeService.findCommandById(Long.valueOf(recipeId)));
40+
41+
return "recipe/ingredient/list";
42+
}
43+
44+
@GetMapping("recipe/{recipeId}/ingredient/{id}/show")
45+
public String showRecipeIngredient(@PathVariable String recipeId,
46+
@PathVariable String id, Model model){
47+
model.addAttribute("ingredient", ingredientService.findByRecipeIdAndIngredientId(Long.valueOf(recipeId), Long.valueOf(id)));
48+
return "recipe/ingredient/show";
49+
}
50+
51+
@GetMapping("recipe/{recipeId}/ingredient/new")
52+
public String newRecipe(@PathVariable String recipeId, Model model){
53+
54+
//make sure we have a good id value
55+
RecipeCommand recipeCommand = recipeService.findCommandById(Long.valueOf(recipeId));
56+
//todo raise exception if null
57+
58+
//need to return back parent id for hidden form property
59+
IngredientCommand ingredientCommand = new IngredientCommand();
60+
ingredientCommand.setRecipeId(Long.valueOf(recipeId));
61+
model.addAttribute("ingredient", ingredientCommand);
62+
63+
//init uom
64+
ingredientCommand.setUom(new UnitOfMeasureCommand());
65+
66+
model.addAttribute("uomList", unitOfMeasureService.listAllUoms());
67+
68+
return "recipe/ingredient/ingredientform";
69+
}
70+
71+
@GetMapping("recipe/{recipeId}/ingredient/{id}/update")
72+
public String updateRecipeIngredient(@PathVariable String recipeId,
73+
@PathVariable String id, Model model){
74+
model.addAttribute("ingredient", ingredientService.findByRecipeIdAndIngredientId(Long.valueOf(recipeId), Long.valueOf(id)));
75+
76+
model.addAttribute("uomList", unitOfMeasureService.listAllUoms());
77+
return "recipe/ingredient/ingredientform";
78+
}
79+
80+
@PostMapping("recipe/{recipeId}/ingredient")
81+
public String saveOrUpdate(@ModelAttribute IngredientCommand command){
82+
IngredientCommand savedCommand = ingredientService.saveIngredientCommand(command);
83+
84+
log.debug("saved receipe id:" + savedCommand.getRecipeId());
85+
log.debug("saved ingredient id:" + savedCommand.getId());
86+
87+
return "redirect:/recipe/" + savedCommand.getRecipeId() + "/ingredient/" + savedCommand.getId() + "/show";
88+
}
89+
90+
@GetMapping("recipe/{recipeId}/ingredient/{id}/delete")
91+
public String deleteIngredient(@PathVariable String recipeId,
92+
@PathVariable String id){
93+
94+
log.debug("deleting ingredient id:" + id);
95+
ingredientService.deleteById(Long.valueOf(recipeId), Long.valueOf(id));
96+
97+
return "redirect:/recipe/" + recipeId + "/ingredients";
98+
}
99+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package guru.springframework.controllers;
2+
3+
import guru.springframework.commands.RecipeCommand;
4+
import guru.springframework.services.RecipeService;
5+
import lombok.extern.slf4j.Slf4j;
6+
import org.springframework.stereotype.Controller;
7+
import org.springframework.ui.Model;
8+
import org.springframework.web.bind.annotation.GetMapping;
9+
import org.springframework.web.bind.annotation.ModelAttribute;
10+
import org.springframework.web.bind.annotation.PathVariable;
11+
import org.springframework.web.bind.annotation.PostMapping;
12+
13+
/**
14+
* Created by jt on 6/19/17.
15+
*/
16+
@Slf4j
17+
@Controller
18+
public class RecipeController {
19+
20+
private final RecipeService recipeService;
21+
22+
public RecipeController(RecipeService recipeService) {
23+
this.recipeService = recipeService;
24+
}
25+
26+
@GetMapping("/recipe/{id}/show")
27+
public String showById(@PathVariable String id, Model model){
28+
29+
model.addAttribute("recipe", recipeService.findById(Long.valueOf(id)));
30+
return "recipe/show";
31+
}
32+
33+
@GetMapping("recipe/new")
34+
public String newRecipe(Model model){
35+
model.addAttribute("recipe", new RecipeCommand());
36+
37+
return "recipe/recipeform";
38+
}
39+
40+
@GetMapping("recipe/{id}/update")
41+
public String updateRecipe(@PathVariable String id, Model model){
42+
model.addAttribute("recipe", recipeService.findCommandById(Long.valueOf(id)));
43+
return "recipe/recipeform";
44+
}
45+
46+
@PostMapping("recipe")
47+
public String saveOrUpdate(@ModelAttribute RecipeCommand command){
48+
RecipeCommand savedCommand = recipeService.saveRecipeCommand(command);
49+
50+
return "redirect:/recipe/" + savedCommand.getId() + "/show";
51+
}
52+
53+
@GetMapping("recipe/{id}/delete")
54+
public String deleteById(@PathVariable String id){
55+
56+
log.debug("Deleting id: " + id);
57+
58+
recipeService.deleteById(Long.valueOf(id));
59+
return "redirect:/";
60+
}
61+
}

0 commit comments

Comments
 (0)