Part of an application I'm writing is an "editor" form for a task. Some of the task entity fields can be null, for example: date completed.
I'm using a Binder
to bind the entity fields to the editor fields and also perform validation. I'm running into an issue where validation fails because items (like date completed) are null. It's OK for this to be null. However, the field is flagged as "value null" and the entity is not saved.
Is there a way to tag what are essentially optional fields so that nulls are allowed? Of course, if a value has been entered, then it needs to be validated.
Task.java (the entity)
@Entity
public class Task extends AbstractEntity {
...
// These are optional fields.
private Long dateDue;
private Long dateStarted;
private Long dateCompleted;
...
}
EditTaskForm.java
public class EditTaskForm extends VerticalLayout {
private DatePicker dateDue;
private DatePicker dateStarted;
private DatePicker dateCompleted;
...
private void bindData() {
binder = new Binder<>(Task.class);
...
binder.forField(dateDue)
.withConverter(new LocalDateToLongConverter())
.bind("dateDue");
binder.forField(dateStarted)
.withConverter(new LocalDateToLongConverter())
.bind("dateStarted");
binder.forField(dateCompleted)
.withConverter(new LocalDateToLongConverter())
.bind("dateCompleted");
binder.withValidator(new TaskValidator());
}
private void validateAndSave() {
try {
binder.writeBean(task);
fireEvent(new SaveEvent(this, task));
} catch (ValidationException e) {
logger.error("field validation errors:");
e.getFieldValidationErrors().forEach(er -> {
logger.error("status: {}", er.getStatus());
logger.error("message: {}", er.getMessage().get());
logger.error("field: {}", er.getField().getValue());
});
logger.error("bean validation errors:");
e.getBeanValidationErrors().forEach(er -> {
logger.error(er.getErrorMessage());
});
}
}
...
}
If I run the application, create a new task, don't specify a value for any of those optional fields and attempt to validate and save, each field on the form is flagged with the message "value null" and highlighted.
UPDATE:
It turns out the "value null" was coming from the LocalDateToLongConverter
. Here it is (note the commented out code):
public class LocalDateToLongConverter implements Converter<LocalDate, Long> {
private ZoneId zoneId;
public LocalDateToLongConverter(ZoneId zoneId) {
this.zoneId = Objects.requireNonNull(zoneId, "Zone id cannot be null");
}
public LocalDateToLongConverter() {
this(ZoneId.systemDefault());
}
@Override
public Result<Long> convertToModel(LocalDate value, ValueContext context) {
if (value != null) {
return Result.ok(Date.from(value.atStartOfDay(zoneId).toInstant()).getTime());
} else {
return Result.ok(null);
// return Result.error("value null");
}
}
@Override
public LocalDate convertToPresentation(Long value, ValueContext context) {
if (value != null) {
return Instant.ofEpochMilli(value).atZone(zoneId).toLocalDate();
} else {
return null;
}
}
}
question from:
https://stackoverflow.com/questions/66064518/vaadin-14-how-to-allow-null-values-in-form-validation 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…