How to validate the Nested Objects using Spring Validation in Spring boot?

Viewed 381

I am developing a project in which one of the many requirement is to custom validate the two objects for which I am passing both objects to the controller from a single form. I am frequently receiving the exception on the particular statement which I don't know how to manage or solve it.

package com.practive.course.configure;

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

import com.practive.course.model.Credentials;
import com.practive.course.model.Student;

@Component
public class StudentValidator implements Validator {

    private final Validator credentialValidator;

    public StudentValidator(Validator credentialValidator) {
        if (credentialValidator == null) {
            throw new IllegalArgumentException(
              "The supplied [Validator] is required and must not be null.");
        }
        if (!credentialValidator.supports(Credentials.class)) {
            throw new IllegalArgumentException(
              "The supplied [Validator] must support the validation of [Address] instances.");
        }
        this.credentialValidator = credentialValidator;
    }

    /**
    * This Validator validates Customer instances, and any subclasses of Customer too
    */
    public boolean supports(Class clazz) {
        return Student.class.isAssignableFrom(clazz);
    }

    public void validate(Object target, Errors errors) {
         Student student = (Student) target;

         System.out.println(student.getMyname());
         System.out.println("below");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "NotEmpty"); //this line generates the exception
        System.out.println("above");
        //ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required");




        try {
            errors.pushNestedPath("credentials");
            ValidationUtils.invokeValidator(this.credentialValidator, student.getCred(), errors);
        } finally {
            errors.popNestedPath();
        }
    }
}


@PostMapping("/registration")
    public String postRegister(Student student,Credentials credential,BindingResult bindingResult,RedirectAttributes redirect) {

        try{
            validator.validate(student,bindingResult);
        }catch(Exception e) {
            System.out.println("problem is here "+e.getMessage());
        }

        try {
            if(bindingResult.hasErrors()) {
                return "registration";
            }
        }catch(Exception e) {
            System.out.println("problem is in biding "+e.getMessage());
        }
        appService.registerStudent(student,credential);
        return "redirect:/login";
    }

package com.practive.course.model;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

@Entity
public class Student {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    private String myname;
    private String mobile;
    private String email;

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="credid")
    private Credentials cred;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getMyname() {
        return myname;
    }

    public void setMyname(String myname) {
        this.myname = myname;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Credentials getCred() {
        return cred;
    }

    public void setCred(Credentials cred) {
        this.cred = cred;
    }

}


package com.practive.course.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Credentials {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    private String username;
    private String password;
    private String usermobile;
    private Role roles;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getUsermobile() {
        return usermobile;
    }
    public void setUsermobile(String usermobile) {
        this.usermobile = usermobile;
    }
    public Role getRoles() {
        return roles;
    }
    public void setRoles(Role roles) {
        this.roles = roles;
    }


}

The stacktrace :

Invalid property 'email' of bean class [com.practive.course.model.Credentials]: Bean property 'email' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

The above exception is being generated when I am trying to validate

1 Answers

The stacktrace shows that Invalid property 'email' of bean class [com.practive.course.model.Credentials] , the validator method is trying to get the email property of the Credentials object while from your code it is visible that the "email" is part of the Student class.

Related