0

Consider this code

import org.hibernate.validator.constraints.Range;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Optional;
import java.util.Set;

class Scratch {
    public static void main(String[] args) {
        final Person alice = new Person("Alice", 54, Optional.of("Tiddles"));// Valid has pet with valid name
        final Person frank = new Person("Frank", 75, Optional.of("  ")); // Should be invalid pet name is blank
        final Person oliver = new Person("Oliver", 75, null); // Should be invalid pet name is null
        final Person bob = new Person("Bob", 33, Optional.empty()); // Valid no pet

        final List<Person> people = List.of(alice, frank, oliver, bob);

        final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

        for (Person person : people) {
            final Set<ConstraintViolation<Person>> violations = validator.validate(person);
            if (violations.isEmpty()) {
                System.out.println(String.format( "[%s] is valid", person.name));
            } else {
                System.out.println(String.format("[%s] is invalid [%s]", person.name, violations));
            }

        }
    }

    static class Person {
        @NotBlank
        public String name;
        @Range(min = 0, max = 150)
        public int age;
        @NotNull
        public Optional<@NotBlank String> petsName;

        public Person(String name, int age, Optional<String> petsName) {
            this.name = name;
            this.age = age;
            this.petsName = petsName;
        }
    }
}

The question is how to validate Optional fields. Its valid for petsName to be an empty Optional (i.e. no pet) but if there is a pet it should have a valid (i.e. non-blank) name. When I run this code it outputs

Dec 22, 2021 11:50:25 AM org.hibernate.validator.internal.util.Version <clinit>
INFO: HV000001: Hibernate Validator 6.1.7.Final
[Alice] is valid
[Frank] is invalid [[ConstraintViolationImpl{interpolatedMessage='must not be blank', propertyPath=petsName, rootBeanClass=class Scratch$Person, messageTemplate='{javax.validation.constraints.NotBlank.message}'}]]
[Oliver] is invalid [[ConstraintViolationImpl{interpolatedMessage='must not be null', propertyPath=petsName, rootBeanClass=class Scratch$Person, messageTemplate='{javax.validation.constraints.NotNull.message}'}]]
[Bob] is invalid [[ConstraintViolationImpl{interpolatedMessage='must not be blank', propertyPath=petsName, rootBeanClass=class Scratch$Person, messageTemplate='{javax.validation.constraints.NotBlank.message}'}]

So its close to working. Only the last case of bob is wrong. Is there any obvious solution i'm missing?

James Mudd
  • 1,816
  • 1
  • 20
  • 25
  • An _optional_ field? Does not make sense to me. Why not simply having a `private String petsName` that can be `null`? – Seelenvirtuose Dec 22 '21 at 12:09
  • You shouldn't use Optionals as class attributes. https://stackoverflow.com/questions/29033518/is-it-a-good-practice-to-use-optional-as-an-attribute-in-a-class – Nikolai Shevchenko Dec 22 '21 at 12:34
  • 1
    @Nikolai but [also](https://stackoverflow.com/a/26328555/16320675) "There's nothing wrong with Optional that it should be avoided" (the source of the text quoted in accepted answer of the question you provided the link to, that is, Brian Goetz) - Actually that link does not say that it shouldn't be used as property, it just states that it was not intended to be used as such (I would not use it, since just adding an additional *state* - variable itself being `null`) – user16320675 Dec 22 '21 at 13:47
  • @user16320675 I agree with you. My intent (maybe it's not clear) is that when you use non-standard approach, then you have to deal with some unpredicted behaviour. E.g. when you use non-JavaBean-conventional naming for attributes (e.g.`user_id` instead of `userId`) in your java classes, Jackson might work not as intended :) – Nikolai Shevchenko Dec 22 '21 at 17:11

0 Answers0