How to pass ID to controller? - java

I have a form
<form method="POST" action="/user/${id}">
<input type="text" name="id" value="${id}" placeholder="Input Id">
<button>Get User</button>
</form>
How to pass id to controller?
#RequestMapping (value = "/user/{id}", method = RequestMethod.POST)
public String getStudent(#PathVariable ("id") Integer id, Model model){
User savedUser = userRepository.get(id);
model.addAttribute("user", savedUser);
return "user";
}

You could do this way , consider i am passing the ${id} value through the query string
Get User
And in your controller,
#RequestMapping ("user")
public String getStudent(#RequestParam Integer id, Model model){
User savedUser = userRepository.get(id);
model.addAttribute("user", savedUser);
return "user";
}
Hope this helps !

Related

Validate a field from form using the BindingResult :Spring

How to validate an integer type value in a form input using the BindingResult in spring?
When I try to validate the input I am getting an exception.I have gone through many posts but did not understand the concept completely.
The problem here isn't with validation, it is with the data binding. Data binding happens before validation, and validation is only invoked when all fields have been converted and bound correctly. In my case, the binding step is failing.Please correct me if I am wrong here.
<div class="form-group">
<div class="col-sm-9">
<label th:if="${#fields.hasErrors('age')}" th:errors="age"
class="validation-message"></label>
<input type="number" th:field="*{age}"
placeholder="Age" class="form-control" />
</div>
</div>
Code to map the request
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public ModelAndView createNewUser(#Valid User user, BindingResult bindingResult) {
ModelAndView modelAndView = new ModelAndView();
User userExists = userService.findUserByEmail(user.getEmail());
if (userExists != null) {
bindingResult
.rejectValue("email", "error.user",
"There is already a user registered with the email provided");
}
if (bindingResult.hasErrors()) {
modelAndView.setViewName("registration");
} else {
userService.saveUser(user);
modelAndView.addObject("successMessage", "User has been registered succssfully");
modelAndView.addObject("user", new User());
modelAndView.setViewName("registration");
}
return modelAndView;
}
User.class
#Column(name = "age")
#NotEmpty(message = "*age is mandatory")
private Integer age;
Exception:
javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint 'javax.validation.constraints.Size' validating type 'java.lang.Integer'. Check configuration for 'age'
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.throwExceptionForNullValidator(ConstraintTree.java:229) ~[hibernate-validator-5.2.4.Final.jar:5.2.4.Final]
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.getConstraintValidatorNoUnwrapping(ConstraintTree.java:310) ~[hibernate-validator-5.2.4.Final.jar:5.2.4.Final]
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.getConstraintValidatorInstanceForAutomaticUnwrapping(ConstraintTree.java:244) ~[hibernate-validator-5.2.4.Final.jar:5.2.4.Final]
Not empty constraint is used for Strings and collections.
https://docs.jboss.org/hibernate/beanvalidation/spec/2.0/api/javax/validation/constraints/NotEmpty.html.
To verify if an Integer has some value, #NotNull constraint should be used.

Checking for Null Attribute in Thymeleaf Template

I am new to Thymeleaf and am trying to check for a null attribute in my template
<form th:action="#{/saveUser/__${user.id}__}" th:object="${user}" method="post">
The form submits fine if I am editing an existing user with an id already defined, however using the same form to add a new user I get the following
HTTP Status 400 - http://localhost:8080/myApp/saveUser/null"
My controller:
#RequestMapping(value = "/saveUser/{id}", method = RequestMethod.POST)
public String saveUser(#ModelAttribute("user") User user, #PathVariable Long id, Model model) {
model.addAttribute("user", user);
userRepo.save(user); //JPA Repo
return "success";
}
My thought is if I can check for the null id I can plug in a unique one somehow. Better yet, if I could make use of the #GeneratedValue set on my User object's ID then I think I'd be in good shape
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
EDIT Including my user edit form method which returns the same form but pre-populated with the User's model Attributes
#RequestMapping(value = "/edit/user/{id}", method = RequestMethod.GET)
public ModelAndView getUserEditForm(#PathVariable Long id, Model model){
ModelAndView mav = new ModelAndView("userForm");
User user = userRepo.findOne(id);
mav.addObject("userForm", user);
return mav;
}
EDIT 2 Including my whole form (ID is "hidden" from user)
<form th:action="#{/saveUser/__${user.id}__}" th:object="${user}" method="post">
<input id="id" type="hidden" th:field="*{id}" />
<input id="id" type="text" th:field="*{name}" />
<input id="id" type="text" th:field="*{address}" />
<button id="save">Save</button>
</form>
As per discussion assuming that the following method is the one you call which should populate the user object and thus form fails on submission:
#RequestMapping(value = "/saveUser/{id}", method = RequestMethod.POST)
public String saveUser(#ModelAttribute("user") User user, #PathVariable Long id, Model model) {
model.addAttribute("user", user);
userRepo.save(user); //JPA Repo
return "success";
}
The reason that method doesn't work is because you are potentially passing an empty user object to begin with.
To remediate this you need to implement checks to ensure object is not null prior to calling the page.
one solution could be:
#RequestMapping(value = "/saveUser/{id}", method = RequestMethod.POST)
public String saveUser(#ModelAttribute("user") User user, #PathVariable Long id, Model model) {
userRepo.save(user); //JPA Repo
if(user == null) // check if user object is empty
user = new User(); // if user is empty, then instantiate a new user object
model.addAttribute("user", user);
return "success";
}
The above will ensure that when you passing user object to the model, it is always available.
I've temporarily resolved this by creating a new #Controller to accept "null" at the end of the #RequestMapping (which kind of makes sense when creating a new user with a dynamic ID?), and just reimplementing the same logic. So when this is called
http://localhost:8080/myApp/saveUser/null"
It is mapped to my new Controller
#RequestMapping(value = "/saveUser/null", method = RequestMethod.GET)
public ModelAndView saveUser(#ModelAttribute("user") User user, Model model){
model.addAttribute("user", user);
userRepo.save(user);
return "success";
}

How to pass model from view to controller in Spring?

I have a controller
#RequestMapping(value = "/admin/manage/{id}", method = RequestMethod.GET)
public ModelAndView goManage(#PathVariable int id) {
UserAccount userAccount = userAccountService.findUserAccount(id);
ModelAndView mav = new ModelAndView("admin/manage");
mav.addObject("userAccount", userAccount);
return mav;
}
and i pass userAccount model to manage.jsp view. In view I display this model. Example:
<div id="info">
<label>Login:</label><label>${userAccount.userDto.username}</label><br />
<label>Name:</label><label>${userAccount.userDto.firstName}
${userAccount.userDto.lastName}</label>
</div>
<form:form
action="${pageContext.request.contextPath}/admin/go"
modelAttribute="userAccount" method="post">
<input class="myButton" type="submit" value="Go" />
</form:form>
And it's ok, but I want pass this model userAccount from view further to next controller when I clicked button Go. My above form implementation doesen't work. How I can pass object from view? It's possible?
#RequestMapping(value = "/admin/go", method = RequestMethod.POST)
public ModelAndView goWithDrawalInvestment(
#ModelAttribute("userAccount") UserAccount userAccount) {
userAccount.setBalance(0);
mav.addObject("userAccount", userAccountDto);
return mav;
}

Form data not binding with Spring Controller Annotation getting new object after submit

I am not getting form data in spring controller after submitting the form below is my code
#RequestMapping(value = "category/addCategory.htm" , method = RequestMethod.GET)
public String add(Model model) {
if (log.isDebugEnabled()){
log.debug("Invoking listCategory");
}
model.addAttribute("categoryView", new CategoryView());
return "editCategory";
}
#RequestMapping(value = "category/saveCategory.htm", method = RequestMethod.POST)
public String saveCategory(CategoryView categoryView, Model model, BindingResult result) {
Category category = prepareCategoryFromView(categoryView);
categoryService.save(category);
categoryView.setCategoryId(category.getCategoryId());
model.addAttribute("categoryView",categoryView);
return "editCategory";
}
prepareCategoryFromView is a method which is setting the actual values on Category it's hibernate entity, below categoryView
public class CategoryView {
private long categoryId;
private String image = "";
private int parentId;
private boolean top;
private int column = 1;
private int sortOrder = 1;
private boolean status;
private String description;
private String name;
.
.
other variable and setter and getters
}
and the form is
<sf:form method="post" enctype="multipart/form-data" id="form-category" cssClass="form-horizontal" modelAttribute="categoryView">
<sf:label path="name" cssClass="col-sm-2 control-label">Category Name</sf:label>
<sf:input path="name" id="name" name="name" cssClass="form-control" placeholder="Category Name" />
<sf:hidden path="categoryId" id="categoryId" name="categoryId" />
<sf:hidden path="languageId" id="languageId" name="languageId" />
<sf:label path="description" cssClass="col-sm-2 control-label">Category Name</sf:label>
<sf:textarea path="description" cssClass="form-control" placeholder="Description" id="description"/>
.
.
.
</sf:form>
In above form every time I am getting name and description is null (I think it's creating a new view object without given values in form)
Pls let me know, where I am wrong
Remove the enctype="multipart/form-data" from your form tag and try again (with the method arguments in the correct order). #ModelAttribute is not strictly required since your attribute name matches the class name.
I think #ModelAttribute annotation is missing here on CategoryView object.Because as per your form code it is the model attribute which will bind data to the bean in controller.
Attach it with your method argument like below,then you can check the data is binding to it or not.
#RequestMapping(value = "category/saveCategory.htm", method = RequestMethod.POST)
public String saveCategory(#ModelAttribute("categoryView") CategoryView categoryView, Model model, BindingResult result) {
Category category = prepareCategoryFromView(categoryView);
categoryService.save(category);
categoryView.setCategoryId(category.getCategoryId());
model.addAttribute("categoryView",categoryView);
return "editCategory";
}

Spring MVC user data update issue

I’ve an issue with update of user data in Spring MVC app.
So, I have user and I have FORM filled with data from JSP. Now data from FORM overrides all fields of user data with null, except entered in jsp.
In another case – user’s data overrides form’s data.
Help me, please, to do it correctly. I’ve tried a lot of variants but nothing works.
#RequestMapping(value = "/edit", method = RequestMethod.GET)
public ModelAndView updateView(#ModelAttribute(value = "updateForm")
HttpSession session) {
User user = (User) session.getAttribute("user");
UserForm updateForm = new UserForm();
updateForm.setUser(user);
return new ModelAndView("profileupdate", "updateForm", updateForm);
}
#RequestMapping(method = RequestMethod.POST)
public String updateUserProcess(#ModelAttribute(value = "updateForm")
UserForm updateForm,
BindingResult result, Model model,
HttpSession session) {
User user = (User) session.getAttribute("user");
model.addAttribute("updateForm", updateForm);
if (result.hasErrors()) {
return "profileupdate";
}
if (!updatingUser(updateForm, model, user))
model.addAttribute("errorMsg", "Login or Email is already in use!");
return "profileupdate";
}
return "updated";
}
private boolean updatingUser(UserForm updateForm, Model model, User user) {
fillForm(updateForm, user);
user = updateForm.getUser();
//Another case
//user = updateForm.getUser();
//fillForm(updateForm, user);
return userService.updateUser(user);
}
private void fillForm(UserForm updateForm, User user) {
updateForm.setUserId(user.getUserId());
updateForm.setLogin(user.getLogin());
updateForm.setPassword(user.getPassword());
updateForm.setEmail(user.getEmail());
}
}
** UserForm class**
public class UserForm {
private Integer userId;
private String login;
private String name;
private String password;
private String email;
public UserForm() {
}
public User getUser() {
User user = new User();
user.setUserId(userId);
user.setLogin(login);
user.setPassword(password);
user.setName(name);
user.setEmail(email);
return user;
}
public void setUser(User user) {
this.userId = user.getUserId();
this.login = user.getLogin();
this.password = user.getPassword();
this.name = user.getName();
this.email = user.getEmail();
………………………….
getters and setters
}
This is my DAO and Service
#Override
public boolean updateUser(User user) {
return userDao.updateUser(user);
}
#Override
#Transactional
public boolean updateUser(User user) {
if (isUserExists(user)) {
return false;
}
currentSession().update(user);
return true;
}
Updade.jsp
<sf:form name="login"
method="POST"
action="${app}/edit"
modelAttribute="updateForm"
enctype="application/x-www-form-urlencoded">
<label for="login">Login:</label><br>
<input name="login" id="login" type="text" value=""/> <br>
<sf:errors path="login" cssClass="error"/><br>
<br><label for="password">Password:</label>
<br><input name="password" id="password" type="password" value=""/>
<br>
<sf:errors path="password" cssClass="error"/><br>
<br> <input type="submit" name="submit" value="Update"/>
</sf:form>
It would be very hard for spring or hibernate to guess what values are null because user wants them to be null and what are null because they do not have to be touched. You as the progammer have to supply a fully completed object.
There are two common ways to do that :
you suppose null fields should be left untouched and modify fillform accordingly :
if (updateForm.getUserId().isEmpty()) { updateForm.setUserId(user.getUserId()); }
...
you prefil your form with current User value in the get that precedes the post (more common unless you need a post without the get part before)
EDIT
To prefill the form (the jsp part seems to be fine) your controller should put a filled UserFormin the model in the GET method.
#RequestMapping(method = RequestMethod.GET)
public String updateView(#ModelAttribute(value = "updateForm")
UserForm updateForm,
HttpSession session) {
User user = (User) session.getAttribute("user");
updateForm.setUser(user);
return "profileupdate";
}
with updateForm being implicitely in model due to the #ModelAttribute annotation, or
#RequestMapping(method = RequestMethod.GET)
public ModelAndView updateView(HttpSession session) {
updateForm = new UserForm();
User user = (User) session.getAttribute("user");
updateForm.setUser(user);
return new ModelAndView("profileupdate", "updateForm", updateForm);
}
I also removed the value="/edit" because it is not on updateUserProcess and I assumed the "/edit" was allready established on controller.
Well, main problem was in the path on JSP. Instead of handle request through controller I've set just a link to the page. So, advice - be careful and attentive with mappings.
WRONG VERSION OF LINK
<form name="redaction"
action="${pageContext.request.contextPath}/updatepage.jsp"
method="GET"
enctype="application/x-www-form-urlencoded">
<input type="submit" name="submit" value="Redaction"/>
</form>
RIGHT VERSION OF LINK
<form name="redaction"
action="${pageContext.request.contextPath}/edit"
method="GET"
enctype="application/x-www-form-urlencoded">
<input type="submit" name="submit" value="Redaction"/>
</form>
And controller
#RequestMapping(value = "/edit", method = RequestMethod.GET)
public String updateView(UserForm userForm,
HttpSession session,
ModelMap model) {
User user = (User) session.getAttribute("user");
userForm.setUser(user);
model.addAttribute("userForm", userForm);
return "profileupdate";
}
#RequestMapping(value = "/edit.do", method = RequestMethod.POST)
public String updateUserProcess(#ModelAttribute(value = "userForm")
UserForm userForm,
BindingResult result, Model model,
HttpSession session) {
User user = (User) session.getAttribute("user");
session.getAttribute("userForm");
model.addAttribute("userForm", userForm);
userValidator.validate(userForm, result);
if (result.hasErrors()) {
logger.error("Validation error");
return "profileupdate";
}
if (!updatingUser(userForm, model, user)) {
logger.error("User update error!");
logger.error("Login or Email is already in use!");
model.addAttribute("errorMsg", "Login or Email is already in use!");
return "profileupdate";
}
logger.info("User updated!");
return "newuserprofile";
}
Have you checked the values of user.getUserID,user.getLogin(),user.getPassword(),user.getEmail()
in the following segment of code? Is it null or the data you recieved in the model object User?
updateForm.setUserId(user.getUserId());
updateForm.setLogin(user.getLogin());
updateForm.setPassword(user.getPassword());
updateForm.setEmail(user.getEmail());
Please post the code for userService.updateUser(user) so that we can understand more.

Categories