I am trying to binding data from one entity to another.
First entity Car:
public class Car {
@Id
private Long carId;
private String carName;
private Long brandId;
.
.
.
}
refers to the second entity Brand:
public class Brand {
@Id
private Long brandId;
private String brandName;
.
.
.
}
In the view class CarDetailView I am using combobox with brand names, but binder is seted to Car entity
public class CarDetailView extends Div implements BeforeEnterObserver {
private ComboBox<String> brandNames;
private BeanValidationBinder<Car> binder;
private void createBasicLayout(SplitLayout splitLayout) {
brandNames = new ComboBox<>("Brand name");
brandNames.setItems(brandRepository.findAllBrandNames()); //function returns all brandNames from database (e.g. Volkswagen, Volvo, Audi, ...)
}
}
So it returns the correct result into the combobox (combobox contains all brand names), but when I choose value from combobox, it can't be binded into the Car entity.
The problem is, that I need to get the brandId from text in combobox and set it into the Car entity with binder.
I tried to use pairs:
private ComboBox<Pair<Long, String>> brandNames;
where I have seted the brandId (left side) and brandName (right side), but it still can't bind it into the Car, because it throw an exception:
Caused by: java.lang.IllegalStateException: Property type 'java.lang.Long' doesn't match the field type 'com.vaadin.flow.internal.Pair<java.lang.Long, java.lang.String>'. Binding should be configured manually using converter.
Does anyone have an idea how I could do this?
Working result:
I used the Simon Martinelli answer:
public class CarDetailView extends Div implements BeforeEnterObserver {
private ComboBox<Brand> brand;
private BeanValidationBinder<Car> binder;
private void createBasicLayout(SplitLayout splitLayout) {
binder = new BeanValidationBinder<>(Car.class);
binder.bindInstanceFields(this);
brand = new ComboBox<>("Brand name");
brand.setItems(brandRepository.findAllBrands()); //function returns all Brands
Map<Long, Brand> brandMap = new HashMap<>()
{
{
put(2000000L, new Brand(2000000L, "Audi"));
put(2000001L, new Brand(2000001L, "Volvo"));
}
};
binder.forField(brand) //Line 251
.withConverter(new Converter<Brand, Long>() {
@Override superclass
public Result<Long> convertToModel(Brand value, ValueContext context) {
return Result.ok(value == null ? null : value.getBrandId());
}
@Override superclass
public Brand convertToPresentation(Long value, ValueContext context) {
return brandMap.get(value);
}
}).bind(Car::getBrandId, Car::setBrandId);
}
brand.setItemLabelGenerator(brand-> brand.getBrandName());
}