I'm playing around with Quarkus 3.6.3 and Vaadin 24.3.0. I have the problem that the required indicator for mandatory fields are not shown any more when the quarkus application is live reloaded in dev mode due to changes in any of the class files.
Java classes
I have a view showing some text fields and I use BeanValidationBinder to bind the fields to an instance of a JPA entity class User. This class is simple and looks like this:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class User {
@NotNull
@Column
private String firstName;
@NotNull
@Column
private String lastName;
// Getters and Setters
}
For the sake of simplicity, the view class looks like this:
@Route(value = "user", layout = MainLayout.class)
public class UserFormView extends VerticalLayout {
private final TextField firstName = new TextField("First name");
private final TextField lastName = new TextField("Last name");
private final Binder<User> binder = new BeanValidationBinder<>(User.class);
public UserFormView() {
binder.forField(firstName).withNullRepresentation("").bind("firstName");
binder.forField(lastName).withNullRepresentation("").bind("lastName");
binder.readBean(new User());
add(firstName, lastName);
}
}
The problem
After a live reload the variable propertyDescriptor in the method BeanValidationBinder#configureRequired is null and thus the bean validation annotations of the domain class are not processed for setting the required indicator and for the binder's validation.
Now I wonder if the required indicators should also be shown correctly after live reload.
Debugging
From debugging I figured out:
- when initially starting the application, an instance of
PredefinedScopeBeanMetaDataManageris created and holds a beanMetaDataMap of classes with bean validation annotations as instances ofBeanMetaDataImpl. This instance is kept in an instance ofCloseAsNoopValidatorFactoryWrapperwithin the constantLazyFactoryInitializer#FACTORY. - after a live reload the beanMetaDataMap of this instance is cleared and a new instance of
PredefinedScopeBeanMetaDataManageris created which again holds a map of classes with bean validation annotations. But this new instance is not used for further lookups but the old instance with the empty map is used since it is kept in the constant descibed above.
Thanks for the detective work. That is a bug for sure.
From what I can see, there's not much we can do in Quarkus. Vaadin Flow should avoid to store the
ValidatorFactoryin a static field inLazyFactoryInitializer#FACTORY. Or at least clean things up when the app is stopped and create a new one then. The current code would cause class loader leaks with any server reloading the app anyway.Following this comment by Ivan Kaliuzhnyi in the Flow tracker https://github.com/vaadin/flow/issues/4481#issuecomment-1712720926, you should be able to work around it even if it's not pretty at all.
Pasting from the comment to keep history: