Form validation in thymeleaf by Springboot - spring-boot

I am new to the Springboot and Thymeleaf, I am creating a web where i am using form validation where I am trying to validate fields from an entity class to validate non empty fields.
import javax.validation.constraints.NotBlank;
public class Student {
#NotBlank(message = "Name required")
public String name;
#NotBlank(message = "email required")
public String email;
#NotBlank(message = "address required")
public String address;
#NotBlank(message = "username required")
public String username;
#NotBlank(message = "password required")
public String password;
'''
constructor
getter and setter
'''
}
It is not showing error in my html file, showing error on server.
If any one has any idea please help me.

In order this to work add #valid annotation next to #ModelAttribute("student").
public String addUser(#Valid #ModelAttribute("student") Student student, BindingResult result, Model model){
And also try adding #NotEmpty above the field of Student entity. #NotEmpty will check if the object has empty strings.

Try this,
public String addUser(#Valid #ModelAttribute("student") Student student, Model model){
...
}
Also, add #NotNull on entity attributes and check once.

Try out this:
public String addUser(#Valid #ModelAttribute("student") Student student, BindingResult result, Model model){
Also, add #NotNull on entity attributes and check once.

Related

Spring #RequestBody validation issue using #Valid annotation

I am trying to perform validation on Spring Boot #RequestBody JSON object using #Valid annotation.
This JSON object POJO class will contain another nested object.
I have added field-level annotation for the nested object classes.
Also, I have added the #Valid annotation when adding the nested class object in the main object class.
But still, the validation for the nested class objects is not getting triggered when we are not passing the correct object.
Please find the code below for reference.
ExceptionController.class
#RestController
#RequestMapping("/student")
public class ExceptionController {
#PostMapping
#ResponseStatus(HttpStatus.CREATED)
public String createStudent(#Valid #RequestBody Student student, HttpStatus status) {
Student student1 = student;
return "student data created!!";
}
}
Student.class
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Student {
#NotEmpty(message = "First Name field can not be null or empty")
#NotBlank(message = "First Name field can not be blank")
private String firstName;
#NotEmpty(message = "Last Name field can not be null or empty")
#NotBlank(message = "Last Name field can not be blank")
private String lastName;
#Valid
private Subject subject;
}
Subject.class
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Subject {
#NotEmpty(message = "Topic field can not be null or empty")
#NotBlank(message = "Topic field can not be blank")
private String topic;
}
When I am not sending any data for Subject in the request it is not giving any exception and returns HTTP 200 OK status.
Any help will be highly appreciated.
Try adding #NotNull annotation to Subject subject:
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Student {
#NotEmpty(message = "First Name field can not be null or empty")
#NotBlank(message = "First Name field can not be blank")
private String firstName;
#NotEmpty(message = "Last Name field can not be null or empty")
#NotBlank(message = "Last Name field can not be blank")
private String lastName;
#Valid
#NotNull
private Subject subject;
}
Your current validations would only work if you actually send Subject data but with an empty topic attribute.
On another topic, you might drop the #NotEmpty annotations because #NotBlank does not allow null or empty Strings.

Multiple Use of validations in Spring Boot

I have an API with validation on it.
public class ModelVo {
#NotBlank(message = "...")
private String name;
#Pattern(regex="...", message = "...")
private String lastName;
...
}
I use of it
#PostMapping("/path1")
public ResponseEntity<RestResponse<Object>> create(#Valid #RequestBody ModelVo modelvo){
Now I want use of this validation for other method( for instance update API) again but I don't like #Pattern annotation on lastName fild work for second method. Is it possible?
Assuming that for create() you want to validate lastName with #Pattern but for update() you don't want to validate lastName you can achieve this with validation groups.
Your Controller:
#PostMapping("/path1")
public ResponseEntity<RestResponse<Object>> create(#Validated #RequestBody
ModelVo modelvo){
#PutMapping("/path1")
public ResponseEntity<RestResponse<Object>> update(#Validated(BasicInfo.class) #RequestBody
ModelVo modelvo){
Your Model class:
public class ModelVo {
#NotBlank(message = "...", groups = BasicInfo.class)
private String name;
#Pattern(regex="...", message = "...")
private String lastName;
}
You also need to create the BasicInfo class but that has nothing special.
You may get more information from the following links:
https://www.baeldung.com/spring-valid-vs-validated
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/annotation/Validated.html

Find the updated fields on update request

I have a user entity as
#Entity
public class User {
#Id
private Long id;
private String name;
private String address;
// getter / setter
}
And controller method like:
#PutMapping(value = "/user")
public ResponseEntity<?> updateUser(#RequestBody User user) {
userRepository.save(user);
// ...
}
Now What I am trying to do is finding the field that is being updated.
Example:
If the only name is present I need some message like "Updated field is name".
Is there any better way other than comparing the fields one by one with the database stored values.
you need getUser method. for example: userRepository.getUser(user.id)
then you return the result

Spring MVC Based Rest Services Validations for request body

I have Rest Controller in my application which has the code snippet like below:-
#RestController
#RequestMapping("/api/v1/user")
public class UserRestControllerV1 {
#PostMapping("")
public Response registerUser(#RequestBody #Valid final Request<UserDto> request,
final HttpServletRequest httpServletRequest,
BindingResult result){
Response response = new Response(request);
if(result.hasErrors()){
response.setData(new String("Error"));
}else {
response.setData(new String("Test"));
}
return response;
}
The Request Class:-
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Request<T> {
#JsonProperty(value = "co-relation-id")
private String coRelationID;
#NotNull(message = "The request body should be present")
private T data;
/*
..... various other fields
Getters / Setters
*/
}
The UserDto Class :-
public class UserDto {
#NotNull(message = "The username should not be null")
private String username;
#NotNull(message = "The password should not be null")
#JsonIgnore
private String password;
/*
..... various other fields
Getters / Setters
*/
}
Issue : I am having issues with my validations here. The field private T data in the request class gets validated but the fields inside T - in the case UserDto are not getting validated.
So I need to know the approach or code snippet to achieve this.
I have tried configuring the hibernate validator bean in the configuration but it is of no help in the scenario
#Valid constraint will instruct the Bean Validator to delve to the type of its applied property and validate all constraints found there.
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Request<T> {
#JsonProperty(value = "co-relation-id")
private String coRelationID;
//#NotNull(message = "The request body should be present")
#Valid
private T data;
/*
..... various other fields
Getters / Setters
*/
}

Editing data marked as unique

So I have my model which briefly looks like this:
#Column
#NotNull
#Size(min = 3)
private String firstname;
#Column
#NotNull
private String lastname;
#Column
#UniqueUsername(message = "Such username already exists")
private String username;
Then there is the controller
#RequestMapping(value = "editUser/{id}", method = RequestMethod.POST)
public String editUser(#Valid #ModelAttribute("user") User user, BindingResult bindingResult, #PathVariable Long id, Model model) {
if (bindingResult.hasErrors()) {
System.out.println(bindingResult.getAllErrors());
return "editUser" ;
}
model.addAttribute("roles", roleRepository.findAll());
model.addAttribute("user", userService.findOne(id));
userService.editUser(id, user);
return "redirect:/admin/users";
}
this is the view
I'm using thymeleaf as my template engine.
So I've got the simplest form there is consisting of firstname, lastname, username
and I'd like to be able to edit only lastname but when I send the form it violates the unique constraint on my username field ( which is kinda obvious ).
The goal is to be able to edit one of the user's attributes but preserving the others. How do I do it?

Resources