Как правильно задать propertyPath в ConstraintValidatorContext

Есть Constraint аннотация @ValidatePositions. Валидируется объект Receipt, одно из полей которого List<Postition> positions. Нужно провалидировать все позиции и в сообщение об ошибке пробросить только невалидные позиции. Подскажите, как это правильно сделать?

@Data
@NoArgsConstructor
@AllArgsConstructor
@ValidatePositions
class Receipt{
    @Valid
    @NotNull
    @Size(min = 1)
    List<Position> positions;
    
    public boolean someFlag = true;
}

class Position {
    public Integer id;
    public String text;
    public String ean;
    public String plu;
    ...
}

//сама аннотация
@Documented
@Constraint(validatedBy = PositionsValidator.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidatePositions {
    String message() default "";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}


//реализация ConstraintValidator
public class PositionsValidator implements ConstraintValidator<ValidatePositions, Receipt> {
    @Override
    public boolean isValid(Receipt receipt, ConstraintValidatorContext context) {
    var flag = receipt.someFlag;
    var eanError = ValidationUtils.toOptionalError(
            !flag || receipt.positions.stream().map(Position::getEan).noneMatch(StringUtils::isEmpty),
            "Field 'receipt.positions.ean' must not be null"
    );
    
    //в таком виде в propertyPath попадает весь объект Receipt и сообщение становится слишком громоздким
    context.buildConstraintViolationWithTemplate(eanError.get())
            
    //пробовал так, но тоже громоздко. Весь массив не нужен
            .addPropertyNode("positions")
            
    //вроде можно еще как-то так, но не понимаю как указать индекс на конкретную позицию
            .addPropertyNode("position").inIterable().atIndex(0)
    //или так, но аналогично - как передать контейнер и индекс позиции
            .inContainer(Position.class, 0).inIterable().atIndex(0)
            
            .addConstraintViolation();

            return eanError.isEmpty() ? true : false;
    }
}

Ответы (0 шт):