Lab#SB00-2: CRUD User
Spring Boot controllerView CRUD User (and Librarian)
📘 Spring Boot Lab#SB00-2: CRUD User (and Librarian)
CRUD stands for Create, Read, Update, and Delete - the four basic operations for persistent storage of data.
In the context of a LibraryMangement, CRUD operations would allow us to create new users, retrieve information about existing users, update user information, and delete users from the system.
- First, we’ll create our User class and annotate it with @Data, @NoArgsConstructor, and @AllArgsConstructor.
- Next, we’ll create our
UserServiceclass and annotate it with@Service. This class will use aHashMapto store user data, and will expose methods to create, read, update, and delete users. - Next, we’ll create our
UserControllerclass and annotate it with@Controller. This class will handle requests to view, create, update, and delete users. We’ll inject theUserServiceinto the controller using@Autowired. - Finally, we’ll create our
ThymeleafHTMLtemplates. We’ll create anindex.htmlorhome.htmltemplate to display a list of users, acreateUser.htmltemplate to allow users to create new users, and aneditUser.htmltemplate to allow users to edit existing users.
1 Overview
We’ll be using a Java class called User to represent user data.
The @Data annotation is used to generate getters, setters, equals, hashCode, and toString methods for the class. The @NoArgsConstructor and @AllArgsConstructor annotations are used to generate constructors with no arguments and all arguments, respectively.
We’ll also be using a HashMap to store user data, with userId as the key. This will allow us to quickly retrieve user data using the user ID as a lookup key.
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
// generates getters, setters, equals,
// hashCode, and toString methods
@Data
@NoArgsConstructor // generates a no-args constructor
@AllArgsConstructor // generates a constructor with all arguments
public class User {
private String userId;
private String name;
private String address;
private int age;
}We might implement the CRUD operations for our LibraryMangement system:
Create: To create a new user, we’ll need to generate a unique user ID and create a new User object with the provided user data. We can then add the new User object to our HashMap using the generated user ID as the key.Read: To retrieve information about an existing user, we’ll need to look up the User object in our HashMap using the user ID as the key.Update: To update user information, we’ll need to retrieve the User object from our HashMap using the user ID as the key, and then update the relevant properties of the User object.Delete: To delete a user from the system, we’ll need to remove the User object from our HashMap using the user ID as the key.
2 References
2.1 Library5
2.1.1 Repos
2.1.2 Java Classes
2.1.3 Templates Thynmeleaf
2.2 LibraryManagement: controllerView
3 controllerView
3.1 folder-tree project & domains
3.2 Home
This cycle defines a @Controller class that handles requests to the URL "/home". When a request is made, it adds the current date and time to the model object, and then returns the name of the view to be rendered.
The view will have access to the “todayDate” attribute and can use it to display the current date and time.
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Date;
@Controller
public class HomeController {
@RequestMapping("/home")
public String gethome(Model model){
model.addAttribute("todayDate", new Date().toString());
return "home";
}
}4 CRUD: read
4.1 Users
The cycle request-response relies in the @Controller class called UserController, which maps requests to the "/user/users" URL.
It uses an @Autowired UserService to fetch a list of users and adds them to the model, before returning a view called "user/users".
package com.example.myFirstSpring.controller;
import com.example.myFirstSpring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
UserService userService;
@RequestMapping("/users")
public String getAllUsers(Model model){
// fetch all users, add to model
model.addAttribute("users", userService.getAllUsers());
return "user/users";
}
}Here we will define the @Service class, called UserService with a method called getAllUsers, which returns a HashMap of user objects.
The HashMap is populated with 20 fake user objects using a utility method called populateFakeUsers.
package com.example.myFirstSpring.service;
import com.example.myFirstSpring.model.User;
import com.example.myFirstSpring.utils.Utils;
import org.springframework.stereotype.Service;
import java.util.HashMap;
@Service
public class UserService {
public static HashMap<String, User> users = new HashMap<>();
static {
Utils.populateFakeUsers(20, users);
}
public HashMap<String, User> getAllUsers (){
return users;
}
}4.1.1 Code source
4.2 Librarians
Like User request-response cyle read feature (user-case and user-story) we will code the Librarian.
The Librarian cycle request-response would function similarly to the User cycle request-response, but with different URLs, controller methods, and service methods tailored to the Librarian entity.
The
LibrarianControllerwouldmaprequests to the appropriate URLs, such as"/librarian/librarians".These
requestswould be handled by methods in theLibrarianController, which would call methods from theLibrarianServiceto fetch or manipulate data.
The LibrarianService would contain methods for fetching and manipulating data from the Librarian entity, similar to the UserService for the User entity.
- Templates would also be created for rendering views related to the Librarian entity, using
Thymeleafor a similar templating engine.
4.2.1 Code source
5 CRUD: create
5.1 Create book (reference)
In HTML forms, the name and id attributes serve different purposes for form elements:
nameattribute: This attribute defines thenameof the input element, which is used to identify the form data in the request that is sent to the server when the form is submitted. The name attribute is required for all form controls and must be unique within the form.idattribute: This attribute is used to uniquely identify an HTML element. It can be used to target the element withCSSorJavaScript, and can also be used to associate a label with an input element using the for attribute.
The action attribute is used to specify the URL of the server-side script or class/method that will process the form data when the form is submitted.
This attribute is required for all forms and specifies the location where the form data will be sent.
The method attribute is also used to specify the HTTP method that will be used to submit the form data, such as GET or POST.
The for attribute is used to associate a label with an input element.
The for attribute specifies which input element the label belongs to by referring to the id attribute of the input element.
5.2 Create user
- The client sends a
requestto server-controller by anendpointto get the create-user form: Users template
- The server-controller method handles the
requestand sends aresponsewith the create-user form: UserController
- The client renders the create-user form received from server-controller: userForm
<form action="/user/createUser" >
<p>
<label for="name">Name</label>
<input type="text" name="name" id="name"></p>
<p>
<label for="address">address</label>
<input type="text" name="address" id="address"></p>
<p>
<label for="age">age</label>
<input type="number" name="age" id="age" ></p>
<p>
<input type="submit" value="Add new user" />
</form>- The client sends a
requestto add this newusertoHashMap: userForm
- The sever-controller method handles the
request, saves theuserobject in aHashMapand redirects the reponse: UserController
6 CRUD: update
6.1 Update book (reference)
6.2 Update user
- The client sends a
requestto server-controller by anendpointto get the update-user form: Update user template
- The server-controller method handles the
requestand sends a response with the update-user form: UserController
@RequestMapping("/packedUserForm")
public String packedUserForm(@RequestParam("idFromView") String id ,
Model model){
User userFound = userService.findUserById(id);
if (userFound != null){
model.addAttribute("userFromController", userFound);
model.addAttribute("message", "User found");}
else
model.addAttribute("message", "User not found");
return "user/userToUpdateForm";
}- The client renders the update-user form received from server-controller: userForm
<form th:action=
"@{updateUser/{idFromView}
(idFromView=${userFromController.idUser})}"
th:object=
"${userFromController}"
method=
"post">
<p>
<label for="userId">User Id</label>
<input type="number" name="userId" id="userId"
th:field="*{userId}" readonly></p>
<p>
<p>
<label for="name">Name</label>
<input type="text" name="name" id="name"
th:field="*{name}"></p>
<p>
<label for="address">Address</label>
<input type="text" name="address" id="address"
th:field="*{address}"></p>
<p>
<label for="Age">Age</label>
<input type="number" name="age" id="age"
th:field="*{age}" ></p>
<input type="submit" value="Update user"/>
</div>
</form>- The client sends a request to update this
usertoHashMap: userForm
- The sever-controller method handles the request, updates the
userobject in aHashMapand redirects the reponse: UserController and UserService
@PostMapping("/updateUser/{idFromView}")
public String updateUser(@PathVariable("idFromView") String id,
User updatedUser) {
User userFound = userService.findUserById(id);
if (userFound != null) {
userService.updateUserByUser(updatedUser);
return "redirect:/user/users";
} else return "user/userNotFound";
}7 CRUD: delete
- The client sends a
requestto server-controller by anendpointto delete a user: Users template
- The server-controller method handles the
requestand sends a response with the result. It could be success (user deleted) or fail (the deletion operation could not be done): UserController
The @Controller uses userService to call @Service: deleteUserById:
- The server-controller method after handled the request sends the response: redirects the reponse to users: UserController redirect















