Important Notice - Forums is archived
To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
CommitException Property not bound to datasource - need help
I am new to Vaadin and on a tight deadline so I am hoping someone can help me understand what is going on here. I have a form and using BeanFieldGroup but when I call commit it blows up with com.vaadin.data.fieldgroup.FieldGroup$CommitException: Property "brand" not bound to datasource.
This is my backing object.
public class ParameterFormDto {
private Brand brand;
private Category category;
private SubCategory subCategory;
private MasterParameter masterParameter;
private ParameterLevel parameterLevel;
private String levelValue;
private String order;
private String value;
private Date effectiveStartDate;
private Date effectiveEndDate;
public ParameterFormDto() {
}
public Brand getBrand() {
return brand;
}
public void setBrand(Brand brand) {
this.brand = brand;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public SubCategory getSubCategory() {
return subCategory;
}
public void setSubCategory(SubCategory subCategory) {
this.subCategory = subCategory;
}
public MasterParameter getMasterParameter() {
return masterParameter;
}
public void setMasterParameter(MasterParameter masterParameter) {
this.masterParameter = masterParameter;
}
public ParameterLevel getParameterLevel() {
return parameterLevel;
}
public void setParameterLevel(ParameterLevel parameterLevel) {
this.parameterLevel = parameterLevel;
}
public String getLevelValue() {
return levelValue;
}
public void setLevelValue(String levelValue) {
this.levelValue = levelValue;
}
public String getOrder() {
return order;
}
public void setOrder(String order) {
this.order = order;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Date getEffectiveStartDate() {
return effectiveStartDate;
}
public void setEffectiveStartDate(Date effectiveStartDate) {
this.effectiveStartDate = effectiveStartDate;
}
public Date getEffectiveEndDate() {
return effectiveEndDate;
}
public void setEffectiveEndDate(Date effectiveEndDate) {
this.effectiveEndDate = effectiveEndDate;
}
}
And this is my form code.
@SpringComponent
@UIScope
public class AddParameterForm extends FormLayout {
private static final Logger logger = LoggerFactory.getLogger(AddParameterForm.class);
private final ParameterService parameterService;
private BeanFieldGroup<ParameterFormDto> formFieldBindings = new BeanFieldGroup<>(ParameterFormDto.class);
// ui memebers
@PropertyId("brand")
public NativeSelect brand;
private NativeSelect category;
private NativeSelect subCategory;
private NativeSelect parameter;
private NativeSelect level;
private TextField levelValue;
private TextField order;
private TextField value;
private PopupDateField effectiveStart;
private PopupDateField effectiveEnd;
private Button cancelButton;
private Button saveButton;
// data members
private Brand selectedBrand;
private Category selectedCategory;
private SubCategory selectedSubCategory;
private MasterParameter selectedParameter;
private ParameterLevel selectedParameterLevel;
@Autowired
public AddParameterForm(ParameterService parameterService) {
this.parameterService = parameterService;
initUserInterface();
}
private void initUserInterface() {
setVisible(false);
setMargin(true);
setSizeFull();
//formFieldBindings = new BeanFieldGroup<>(ParameterFormDto.class);
// initialize ui components
brand = new NativeSelect("Brand");
brand.setEnabled(true);
category = new NativeSelect("Category");
category.setEnabled(false);
subCategory = new NativeSelect("Sub Category");
subCategory.setEnabled(false);
parameter = new NativeSelect("Parameter");
parameter.setEnabled(false);
level = new NativeSelect("Level");
level.setEnabled(false);
levelValue = new TextField("Level Value");
order = new TextField("Order");
value = new TextField("Value");
effectiveStart = new PopupDateField("Effective Start");
effectiveEnd = new PopupDateField("Effective End");
cancelButton = new Button("Cancel", event -> {
logger.debug("user cancelled adding parameter");
formFieldBindings.discard();
setVisible(false);
closeParentWindow();
Notification.show("Cancelled", Notification.Type.TRAY_NOTIFICATION);
});
saveButton = new Button("Save", event -> {
try {
formFieldBindings.commit();
ParameterFormDto parameter = formFieldBindings.getItemDataSource().getBean();
parameterService.save(parameter);
setVisible(false);
closeParentWindow();
Notification.show("Parameter saved successfully", Notification.Type.TRAY_NOTIFICATION);
}
catch (FieldGroup.CommitException e) {
Notification.show("Error while saving parameter", Notification.Type.ERROR_MESSAGE);
logger.error("Error saving parameter", e);
}
});
effectiveStart.setDateFormat("MM/dd/yyyy HH:mm");
effectiveStart.setResolution(Resolution.MINUTE);
effectiveEnd.setDateFormat("MM/dd/yyyy HH:mm");
effectiveEnd.setResolution(Resolution.MINUTE);
// validation logic
effectiveStart.addValidator((Validator) value1 -> {
if (value1 == null) {
throw new Validator.InvalidValueException("Effective Start Time cannot be null");
}
try {
java.util.Calendar cal = java.util.Calendar.getInstance();
cal.setTime((Date) value1);
} catch (Exception e) {
throw new Validator.InvalidValueException("Effective Start Time is invalid");
}
});
order.addValidator(value1 -> {
if (value1 == null) {
throw new Validator.EmptyValueException("Order cannot be blank");
}
//if (Integer.parseInt((String) value1) < 0) {
// throw new Validator.InvalidValueException("Order can't be negative");
//}
});
value.addValidator(value1 -> {
if (value1 == null || value1.equals("")) {
throw new Validator.EmptyValueException("Please provide a parameter value");
}
});
levelValue.addValidator(value1 -> {
if (value1 == null || value1.equals("")) {
throw new Validator.EmptyValueException("Please provide a level value");
}
});
effectiveEnd.addValidator(value1 -> {
if (value1 != null) {
java.util.Calendar today = java.util.Calendar.getInstance();
today.set(java.util.Calendar.MINUTE, 0);
today.set(java.util.Calendar.SECOND, 0);
today.set(java.util.Calendar.HOUR_OF_DAY, 0);
if (((Date) value1).getTime() < today.getTimeInMillis()) {
throw new Validator.InvalidValueException("Effective end time cannot be in the past");
}
}
});
BeanItemContainer<Brand> brandBeanItemContainer =
new BeanItemContainer<Brand>(Brand.class, parameterService.getBrands());
BeanItemContainer<Category> categoryBeanItemContainer =
new BeanItemContainer<Category>(Category.class, parameterService.getCategories());
BeanItemContainer<ParameterLevel> parameterLevelBeanItemContainer =
new BeanItemContainer<ParameterLevel>(ParameterLevel.class, parameterService.getLevels());
level.setContainerDataSource(parameterLevelBeanItemContainer);
level.setItemCaptionPropertyId("level");
level.addValueChangeListener(event -> {
ParameterLevel parameterLevel = (ParameterLevel) event.getProperty().getValue();
if (parameterLevel != null && parameterLevel.getId() == 1) {
levelValue.setValue("ANY");
levelValue.setReadOnly(true);
}
else if (parameterLevel != null && parameterLevel.getId() > 1) {
levelValue.setReadOnly(false);
levelValue.setValue("");
}
});
brand.setContainerDataSource(brandBeanItemContainer);
brand.setItemCaptionPropertyId("name");
brand.addValueChangeListener(event -> {
selectedBrand = (Brand) event.getProperty().getValue();
if (selectedBrand != null) {
category.setEnabled(true);
category.setContainerDataSource(categoryBeanItemContainer);
category.setItemCaptionPropertyId("category");
}
});
category.addValueChangeListener(event -> {
selectedCategory = (Category) event.getProperty().getValue();
if (selectedCategory != null) {
subCategory.setEnabled(true);
BeanItemContainer<SubCategory> subCategoryBeanItemContainer =
new BeanItemContainer<SubCategory>(SubCategory.class,
parameterService.getSubCategories(selectedCategory.getId()));
subCategory.setContainerDataSource(subCategoryBeanItemContainer);
subCategory.setItemCaptionPropertyId("subCategory");
}
});
subCategory.addValueChangeListener(event -> {
selectedSubCategory = (SubCategory) event.getProperty().getValue();
if (selectedSubCategory != null) {
parameter.setEnabled(true);
BeanItemContainer<MasterParameter> masterParameterBeanItemContainer =
new BeanItemContainer<MasterParameter>(MasterParameter.class,
parameterService.getMasterParam(selectedBrand.getId(), selectedSubCategory.getId()));
parameter.setContainerDataSource(masterParameterBeanItemContainer);
parameter.setItemCaptionPropertyId("parameterName");
}
});
parameter.addValueChangeListener(event -> {
selectedParameter = (MasterParameter) event.getProperty().getValue();
if (selectedParameter != null) {
level.setEnabled(true);
order.setEnabled(true);
value.setEnabled(true);
effectiveStart.setEnabled(true);
effectiveEnd.setEnabled(true);
}
});
formFieldBindings.buildAndBindMemberFields(this);
addComponent(brand);
addComponent(category);
addComponent(subCategory);
addComponent(parameter);
addComponent(level);
addComponent(levelValue);
addComponent(order);
addComponent(value);
addComponent(effectiveStart);
addComponent(effectiveEnd);
HorizontalLayout horizontalLayout = new HorizontalLayout(saveButton, cancelButton);
horizontalLayout.setSpacing(true);
horizontalLayout.setMargin(false);
addComponent(horizontalLayout);
brand.focus();
}
@Override
public MainUI getUI() {
return (MainUI) super.getUI();
}
private void closeParentWindow() {
((AddParameterWindow) super.getParent().getParent()).close();
}
}
You seem to be missing the formFieldBindings.setItemDataSource() call.
I'm confused what I would pass it in this context. I think what is making this complicated is all my NativeSelect objects are bound to a POJO instead of an enum or String. Is there a example of how to accomplish this?
formFieldBindings.setItemDataSource(new ParameterFormDto());
That seemed to work!!!!
It's perfectly fine to bind to a POJO. The selected value of the select will be the POJO itself, so it works. The only thing to look out for is that you need to either a) have a toString() in your POJO or b) manually set the caption for the items in order to get human readable alternatives.
Thanks for the help! I was stuck on that for a good day. This is a really cool framework once you get into it!
Thanks! Glad I could help.
It looks like you could also simplify your code a bit by using setRequired() instead of manually checking for empty values in some of those fields.