A toy recipe application following instruction of an online Spring Framework course
-
Create needed POJOs as Spring Data JPA Entity Data Model:
- Create Entity:
Category
,Difficulty
,Ingredient
,Notes
,Recipe
, andUnitOfMeasure
- Establish relationships
- Create Entity:
-
Create Spring Data Repositories
CategoryRepository
,RecipeRepository
, andUnitOfMeasureRepository
-
Create Service Layer
- Interface
RecipeService
and its implementation - Two methods:
getRecipes()
andfindById(Long id)
- Interface
-
Initialize database with Spring
- a data.sql file: insertion statement to set description property for category and unit_of_measure
-
Initialize data in DataLoader
- Retrieve all UnitOfMeasure and Category from database
- Create 2 recipes and save them to recipeRepository
-
Create fundemental View layer using Thymeleaf
- At first, only index page showing two recipe (id and description)
- Add a page showing all details of a particular recipe (on path
"/recipe/{recipeId}/show"
)- Add a view link on Index page
<a href="#" th:href="@{/recipe/" + ${recipe.id} + "/show}">View</a>
- Thymeleaf generate the url when clicked
- Create a RecipeController
- RecipeController has a function
public String showById(@PathVariable String id, Model model)
annotated by@GetMapping({"/recipe/{id}/show"})
- When users clicked on the View link on Index page, they are redirected to url
"/recipe/{id}/show"
and the functionshowById(@PathVariable String id, Model model)
executes.
- RecipeController has a function
- Create a show.html to display the detailed recipe
showById(@PathVariable String id, Model model)
return the show.html to the user
- Add a view link on Index page
-
Add functionality of processing form posts with Spring MVC
-
Create Command Object and Type Conversions
- How Command Object and Type converters work:
- Take in Command Objects
- Convert command objects to any existing Entities
- Persist the converted object to the database
- Get entities out of the database
- Convert entities to Command Objects
- Why we need them: will not expose domain entities to the Web Layer or transmit over the network
- What we need:
- Command Object mimics entity
- Converters: from command object to entity and from entity to command object
- Service that can accept a command object, convert it, save it to the database, return an entity, and convert it to the command object
- How Command Object and Type converters work:
-
Add functionalities
-
Allow to create a recipe
- On path
/recipe/new
, users can create a new recipe. The new recipe will be saved to database and show on the Index page - Steps
- Create a
recipeform.html
<form ... method="post">
- RecipeService
- Add a function
public RecipeCommand saveRecipeCommand(RecipeCommand recipeCommand)
.- The function accepts a RecipeCommand, convert it to a Recipe, save it to recipeRepository, and return back a RecipeCommand
- Add a function
- RecipeController
- Add a function
public String newRecipe(Model model)
annotated by@GetMapping("recipe/new")
.- The function will pass a RecipeCommand object to
recipeform.html
, and return the recipeform.html to the user. The user can enter required information for a new recipe.
- The function will pass a RecipeCommand object to
- Add a function
public String saveOrUpdate(@ModelAttribute RecipeCommand command)
annotated by@PostMapping( "recipe")
.- The function executes when getting a post to
/recipe
path. - The function will save the new recipe to recipeRepository and redirect the user to the page showing details of the newly created recipe.
@ModelAttribute
is the annotation that tells Spring to bind the form post parameters to the RecipeCommand object.
- The function executes when getting a post to
- Add a function
- Create a
- On path
-
Allow to update a recipe
- On path
recipe/{id}/update
(Index Page contains an "Update" button that directs users to this path), users can update a recipe. The updated recipe will be saved to database. - Steps
- RecipeService
- Add a function
public RecipeCommand findCommandById(Long l)
.- The function finds a recipe with a specific id value and converts it to a RecipeCommand object.
- Add a function
- RecipeController
- Add a function
public String updateRecipe(@PathVariable String id, Model model)
annotated by@GetMapping("recipe/{id}/update")
- The function passes a RecipeCommand object with specified id to
recipeform.html
, and return the recipeform.html to the user. The user can modified information for that recipe.
- The function passes a RecipeCommand object with specified id to
- Function
saveOrUpdate(@ModelAttribute RecipeCommand command)
will execute when user submit therecipeform.html
.
- Add a function
- RecipeService
- On path
-
Allow to delete a recipe
- Once on path
recipe/{id}/delete
(Index Page contains an "Delete" button that directs users to this path), the recipe with specified id will be deleted. - Steps
- RecipeService
- Add a function
public void deleteById(Long l)
.- The function deletes a recipe with specified id from recipeRepository
- Add a function
- RecipeController
- Add a function
public String deleteById(@PathVariable String id)
annotated by@GetMapping("recipe/{id}/delete")
- The function calls
recipeService.deleteById(Long.valueOf(id))
and redirects user to the index page.
- The function calls
- Add a function
- RecipeService
- Once on path
-
Allow to view, update, create, and delete an ingredient.
-
Allow to upload images, persisting images to database, and displaying images from database
-
-