Spring CRUD - update with #ModelAttribute - spring

I have an update method in my controller:
#RequestMapping(value = Constants.UPDATE, method = RequestMethod.POST)
public ModelAndView updateProduct(#ModelAttribute("productModel") ProductModel productModel) {
productService.updateProduct(productModel);
ModelAndView modelAndView = new ModelAndView("redirect:/showProducts");
return modelAndView;
}
The problem is when I'm doing an update in the form, all of the fields has to be submitted, if I leave a field empty - I get an error - The request sent by the client was syntactically incorrect. So what would be the best way to make it possible to update only a single column without getting this error? My ProductModel is rather simple I have productName, description and price and my query in the DAO is:
String sql = "UPDATE PRODUCT SET description=?, productName=?, price=? WHERE id=?";

The simplest way would be to read all the product fields from the database before updating, overwrite the ones received from the form, and then update all the fields.

Related

Ignore field from bindingResult validation

I'm using SpringBoot 2.1.3 (Embedded Tomcat) + Thymeleaf 3 + java 8. I have a problem regarding validation of a UserDTO that is similar to follow:
#Data
public class UserDTO {
#NotNull
private String name;
#NotNull
private String surname;
.....
#NotBlank
#Email
#UniqueEmailConstraint // this is a custom validator
private String email;
#NotNull
private String pass;
.......
}
#UniqueEmailConstraint check inside the DB if the email is present or not (just one email for account are admitted). Than I have 2 controller, one for inserting user and another one for updating user
#PostMapping("/save-user")
String saveUser(#ModelAttribute("userDTO") #Valid UserDto userDto, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
return "fragment/form-user";
}
and similar one with some other function:
#PostMapping("/update-user")
String updateUser(#ModelAttribute("userDTO") #Valid UserDto userDto, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
return "fragment/form-user";
}
The problem is that when I selecting a user to modify it, a thymeleaf view is open and show me all data inserted as expected (mail included). If I try to modify another field, for example Address and click submit my controller show an errors because it find the email on DB.
Question is, is there a way to ignore certain field on bindingResult? Because of I would like to ignore the #UniqueMailConstraint error on second controller Validation.
Thanks all
I had the a similar problem hope this helps:
Lets say there is an employee HTML form with two buttons.
One of the buttons should validate the whole form, another button should validate just one single field and ignore the validation for the rest.
#RequestMapping(method = RequestMethod.POST, value = "saveEmployee", params = "action=save")
public ModelAndView saveEmployee(#Valid #ModelAttribute("employee") EmployeeDTO employee, BindingResult bindingResult, final HttpServletRequest request, final Model model) {
ModelAndView mav = new ModelAndView();
//Create a new BindingResult with zero errors
BindingResult newBindingResult = new BeanPropertyBindingResult(employee, "employee");
//Add to the new BindingResult the error which is caused by the field 'employeeNumber'
newBindingResult.addError(bindingResult.getFieldError("employeeNumber"));
//If required, more fields can be added to the new BindingResult
//Check if the new BindingResult contains errors -> only the fields added above.
if (newBindingResult.hasErrors()) {
//Do this, if the new BindingResult contains validation errors
} else {
//Do that, if the new BindingResult does not contain errors validation errors
//If your form contains other validation errors for fields other than 'employeeNumber', the validation for them will be ignored.
}
//Set the view and return it.
mav.setViewName(xxx);
return mav;
}

Stop some validations at the persist time in Spring

Is there a way to stop some validations to be executed at the time of data persist.
I know about
spring.jpa.properties.javax.persistence.validation.mode=none
but I believe that disables all validations, I just want to disable it for some of the fields (Password specifically, as it is encoded by that time and then pattern doesn't match). Thanks!
Update(More Details):
#Pattern(regexp = "^[A-Za-z0-9_#!]+$")
private String password;
I have a password field validated using the above pattern (A-Z, a-z, 0-9 and _,#,!). In the controller it validates success by below code.
#RequestMapping(value = "/adduser", method = RequestMethod.POST)
public ModelAndView signUp(ModelAndView modelAndView, #ModelAttribute #Valid LoginUser loginUser, BindingResult bindingResult) {
LoginUser loginUserAdded = null;
if (!bindingResult.hasErrors()) {
loginUser.setPassword(passwordEncoder.encode(loginUser.getPassword()));
loginUserAdded = createUser(loginUser);
....
But then before persist I encode the password and then it throws error while calling save method in JpaRepository because the password value has been changed by the encoder and it doesnt satisfy the pattern validation applied to it.
Now I am looking for a way by which I can disable validation on this field at the time of persist.

Update one attribute of an Entity with ModelAttribute

How can I update just one or a few atributes of an Entity with spring form and controller?
Lets say it is User Entity and has id, status, name, address etc...
I want to update just name, and address. But when I try to save ather values is null. ı dont want to show all attributes in form logically ( Id, status )
You can use hidden input element to propagate users ID to your view, e.g.
<input type="hidden" name="user-id" value="${editUserForm.id}">
Put it in a form - when a form is submitted, users ID will also be submitted with it (remember to add ID to your form model). Then retrieve user from database using this ID, set fields you want to set and update it.
EDIT:
Example:
your model:
#Entity
public class User{
private Long id;
private String name;
private String surname;
//getters & setters
}
form you use to edit some of the fields (no surname):
public class UserForm{
private Long id;
private String name;
//getters & setters, constructor
}
Controller:
#GetMapping(value="/editUser/{userId}")
public ModelAndView editUser(#PathVariable Long userId){
ModelAndView modelAndView = new ModelAndView("editUser");
User user = // retrieve user from database using userId
modelAndView.addObject("editUserForm", new UserForm(user));
return modelAndView;
}
#PostMapping(value="/editUser")
public ModelAndView postEditUser(#ModelAttribute("editUserForm") UserForm editUserForm){
User userToEdit = //retrive user from database using editUserForm.getId()
userToEdit.setName(editUserForm.getName());
//save user to database
//redirect
}
Of course logic I presented in controllers should be located in service layer, I just want to give you an idea on what to do.

Passing URL parameters to Controller but NOT displayed in URL

I have a search page where I search for list of employees based on some criteria and once the employee list is displayed, I click on one of the Employee name to view the employee details.The search result is displayed in a tabular format and includes Employee Name(only the first name),Employee Id and Full Name of the employee.Employee ID and Full Name are read only.
In my code, when i click on the Employee Name, I should get additional details of the employee via the employee id as shown below:
employee.jsp
Employee Name
EmployeeDetailController.java
#RequestMapping(value = "/employeeDetail.do", method = RequestMethod.GET)
public ModelAndView employeeDetail(#RequestParam(value = "employeeID") final String employeeID,
#RequestParam(value = "fullName") final String fullName, final HttpServletRequest request,
final HttpServletResponse response, final ModelMap modelMap) throws Exception {
As a part of security test, i need to remove the employeeID and fullName from the URL as it exposes the employee data.
Can anybody suggest how to pass the request parameters to the controller class in such a way that the parameters are not visible in URL i:e expected URL should be ${ctx}/employeeProfile/employeeDetail.do?
Thanks in advance.

Spring MVC 3 nested object validation is failing with #Valid

I have following nested objects. I am using #Valid for validation in my controller. Here BindingResult object is not validating name field of Child object. Am I missing anything?
class Parent{
#Valid
private Child child;
//getter and setter for child object
}
class Child{
#NotNull(messag="Name cannot be null")
private String name;
//getter and setter for name
}
My controller validate method
#RequestMapping(value = "/validate", method = RequestMethod.POST)
public #ResponseBody String validate(#Valid #ModelAttribute("parent") Parent parent, BindingResult bindingResult) {
//Here I can see child name value if I say parent.getChild().getName()
// But if parent.getChild().getName() is null, bindingResult.hasErrors() is returning false
}
As far as I know, #NotNull isn't quite right for String validation, since the Spring-model often mapping "no object received" to "blank string" instead.
Please try #NotBlank and sees if the BindingResults return errors.
You can't do it this way. You can't validate nested objects like that.
You have to use a validator.
I was also facing similar problem before sometime.
And after doing 2-3 days R&D I succeeded with validating nested object. I tried to do custom validations for the nested object.
You need to create a custom validator class and autowire it in the controller and in the method call validator.validate(parent, bindingResult) and it will return you the error binded with the nested object field in bindingResult object and then you can display it on jsp page as usual.
Hope this helps you. Cheers.

Resources