I'm trying to validate a userDto class with @Valid sending a form-data from an angular application like this:
Angular Form:
this.form.append('email', this.user.email);
this.form.append('password', this.user.password);
this.form.append('firstName', this.user.firstName);
this.form.append('lastName', this.user.lastName);
this.form.append('photo', this.file.name);
this.form.append('enable', `${this.user.enable}`);
this.form.append('roles', JSON.stringify(this.user.roles));
this.form.append('file', this.file);
this.userService.createUser(this.form)
Controller class:
@PostMapping
public ResponseEntity<Object> save(@Valid UserDto userDto, @RequestPart("file") MultipartFile file) throws IOException {
service.save(userDto.convertToUser(userDto, file.getOriginalFilename()), file);
return new ResponseEntity<>(HttpStatus.CREATED);
}
UserDTO class:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDto {
private Integer id;
@NotEmpty(message = "email is required")
private String email;
@NotEmpty(message = "password is required")
private String password;
@NotEmpty(message = "first name is required")
private String firstName;
@NotEmpty(message = "last name is required")
private String lastName;
private String photo;
private String enable;
private String roles;
public User convertToUser(UserDto userDto, String photoName) {
User user = new User();
ObjectMapper mapper = new ObjectMapper();
try {
List<Role> rolesDto =
Arrays.asList(mapper.readValue(userDto.getRoles(),Role[].class));
Set<Role> roles = Set.copyOf(rolesDto);
user.setId(this.id);
user.setEmail(this.email);
user.setPassword(this.password);
user.setFirstName(this.firstName);
user.setLastName(this.lastName);
user.setPhoto(photoName);
user.setEnable(Boolean.parseBoolean(this.enable));
user.setRoles(roles);
} catch (Exception e) {
System.out.println(e.getMessage());
}
return user;
}
}
But if I pass an empty form-data the class that throws an exception is my User class, i wanted that the UserDto throw the exception not the User class.
I tried to use the @RequestBody annotation with @Valid but i'm using formdata in angular not json format.
Is there a way to validate a form-data in spring boot passing the form to a DTO class that do not have an @Entity annotation ?
CodePudding user response:
You can use the Validator
interface from org.hibernate.validator
to validate DTO's. For more info about Hibernate Validator. Or you can look through Spring boot : non-entity bean validation not working and Why does validation not work on objects of type DTO, but only on entities.
public class Car {
@NotNull
private String manufacturer;
@NotNull
@Size(min = 2, max = 14)
private String licensePlate;
@Min(2)
private int seatCount;
public Car(String manufacturer, String licencePlate, int seatCount) {
this.manufacturer = manufacturer;
this.licensePlate = licencePlate;
this.seatCount = seatCount;
}
//getters and setters ...
}
package org.hibernate.validator.referenceguide.chapter01;
import java.util.Set;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class CarTest {
private static Validator validator;
@BeforeClass
public static void setUpValidator() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Test
public void manufacturerIsNull() {
Car car = new Car( null, "DD-AB-123", 4 );
Set<ConstraintViolation<Car>> constraintViolations =
validator.validate( car );
assertEquals( 1, constraintViolations.size() );
assertEquals( "must not be null", constraintViolations.iterator().next().getMessage() );
}
@Test
public void licensePlateTooShort() {
Car car = new Car( "Morris", "D", 4 );
Set<ConstraintViolation<Car>> constraintViolations =
validator.validate( car );
assertEquals( 1, constraintViolations.size() );
assertEquals(
"size must be between 2 and 14",
constraintViolations.iterator().next().getMessage()
);
}
@Test
public void seatCountTooLow() {
Car car = new Car( "Morris", "DD-AB-123", 1 );
Set<ConstraintViolation<Car>> constraintViolations =
validator.validate( car );
assertEquals( 1, constraintViolations.size() );
assertEquals(
"must be greater than or equal to 2",
constraintViolations.iterator().next().getMessage()
);
}
@Test
public void carIsValid() {
Car car = new Car( "Morris", "DD-AB-123", 2 );
Set<ConstraintViolation<Car>> constraintViolations =
validator.validate( car );
assertEquals( 0, constraintViolations.size() );
}
}