Affects: \<6.1.4>


I have these two model classes

# EmailAddress.java

import jakarta.validation.constraints.Email;

public class EmailAddress {

    @Email
    private final String value;

    public EmailAddress(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

# Person.java
import jakarta.validation.Valid;

public class Person {

    @Valid
    private EmailAddress email;

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

    public EmailAddress getEmail() {
        return email;
    }
}

It is my test code

@ExtendWith(SpringExtension.class)
public class PersonTest {

    @TestConfiguration
    public static class TestConfig {

        @Bean
        public LocalValidatorFactoryBean validator() {
            return new LocalValidatorFactoryBean();
        }       
    }

    @Autowired
    private LocalValidatorFactoryBean validator;

    @Test
    public void testInvalidEmailAddress() {
        Person person = new Person();
        EmailAddress email = new EmailAddress("invalid");
        person.setEmail(email);

        Errors errors = validator.validateObject(person);
        assertEquals(1, errors.getErrorCount());
    }
}

My expectation was LocalValidatorFactoryBean can validate nested object EmailAddress and gives me error. But this code throws IllegalArgumentException.

java.lang.IllegalArgumentException: Cannot retrieve value for field 'email.value' - neither a getter method nor a raw field found
 at org.springframework.validation.SimpleErrors.getFieldValue([SimpleErrors.java:145](vscode-file://vscode-app/c:/Users/uugan/AppData/Local/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at org.springframework.validation.SimpleErrors.rejectValue([SimpleErrors.java:104](vscode-file://vscode-app/c:/Users/uugan/AppData/Local/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at org.springframework.validation.beanvalidation.SpringValidatorAdapter.processConstraintViolations([SpringValidatorAdapter.java:180](vscode-file://vscode-app/c:/Users/uugan/AppData/Local/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate([SpringValidatorAdapter.java:106](vscode-file://vscode-app/c:/Users/uugan/AppData/Local/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))

Comment From: quaff

https://github.com/spring-projects/spring-framework/blob/aa4282d7f86798b0874ef9fee11099198e69dfd3/spring-context/src/main/java/org/springframework/validation/Validator.java#L102-L103

You should use validator.validate() instead:

Set<ConstraintViolation<Person>> set = validator.validate(person);
assertEquals(1, set.size());

or

Errors errors = new BeanPropertyBindingResult(person, "person");
validator.validate(person, errors);
assertEquals(1, errors.getErrorCount());

Comment From: uuganbold

Thank you. Got it.