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.
Object loses collection in property after commit in Form
Hi everyone.
I'll try to post everything relevant to the problem, if something is missing please let me know.
I have the following form:
public class PerfilForm extends FormLTP { //FormLTP is a customComponent with a formlayout as content
private TextField nombre = new TextField("Nombre");
private TextField descripcion = new TextField("Descripción");
private ListSelect operacionesListSelect = new ListSelect
("Operaciones:");
private Perfil perfil;
private FieldGroup binder;
public PerfilForm(ABMPerfiles abmPerfiles) {
operacionesListSelect.setItemCaptionPropertyId("titulo");
binder = new FieldGroup(new BeanItem<>(new Perfil()));
binder.bind(nombre, "nombre");
binder.bind(descripcion, "descripcion");
binder.bind(operacionesListSelect, "operaciones");
addComponent(nombre);
addComponent(descripcion);
addComponent(operacionesListSelect);
addComponent(botonAgregarOperacion);
}
@Override
public void edit(EntidadPersistible p) {
perfil = (Perfil) p;
if (perfil != null) {
binder.setItemDataSource(new BeanItem<>(perfil));
operacionesListSelect.setContainerDataSource(new
OperacionContainer(perfil.getOperaciones()));
setVisible(true);
} else {
setVisible(false);
}
}
@Override
protected Button.ClickListener salvarClick() {
return new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent clickEvent) {
System.err.println("before commit:" + perfil.getOperaciones().size());
binder.commit();
System.err.println("after commit:" + perfil.getOperaciones().size());
(Save...)
}
};
}
}
As you may have guessed, this code prints "before commit:X" with X>0 and "after commit:0".
The Perfil class:
@Entity
public class Perfil implements EntidadPersistible, Serializable,
Cloneable {
private static final long serialVersionUID = -6001060705608045414L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;
@Column(unique = true)
String nombre;
@Column
String descripcion;
@Column
private boolean activo = true;
@Enumerated(EnumType.STRING)
@ElementCollection(targetClass = Operacion.class, fetch = FetchType.EAGER)
private List<Operacion> operaciones = new ArrayList<>();
(...Contructors, getter, setters, hashcode, equals, clone, tostring)
}
So... i can't find out why after commit in the form the object perfil loses it's collection.
I thought i was doing something wrong with the binding, but i can't figure it out.
Also, the problem may be due to the fact that the PerfilForm itself is not a FormLayout, but extends from a CustomComponent with a FormLayout set as content. As a matter of fact, when i changed it to extending a FormLayout, it raised ConversionException when commiting (Operacion to List), which makes me think this is the problem.
Any help will be appreciated. Thank you.
EDIT: I'm using Vaadin 7.5.0.
Hi,
Try using MultiSelectTable from Viritin instead of the ListSelect from core. The ListSelect from core is pretty naive, even in multiselect mode. In your edit method you should also call operacionesListSelect.setContainerDataSource before you bind the new entity.
cheers,
matti
Hi Matti,
thank you very much for your answer. I've just solved the problem while i was trying MultiSelectTable.
The problem was this particular line on PerfilForm(#14):
binder.bind(operacionesListSelect, "operaciones");
I know very little of Vaadin, but i suppose that when you're dealing with a property made of a list of Pojos (and setting containerDataSource manually) you shouldn't bind it. Just removing that line solved the problem.
As a side note, i found some of Viritin components very helpful and will be trying them soon.
Thanks a lot, 3 days of frustration ended.
Omar
Hi,
I think you still need to do the bind, or then manually move the new value form the field to your domain object. The two "nasty" things you have here:
* You just need to populate options (setContainerDataSource) before you bind it because setting new container datasource also resets the field value to null (and the bound property in you domain object).
* By default, multiselect components in Vaadin are quite naive and they only work with java.util.Set type (the AbstractSelect classes sets option into Set and then uses setter for the bound property). This is why I pointed you to MultiSelectTable as it is more compatible with various collection types.
cheers,
matti
Yes, i very much agree with both.
...but no, i did not need to do the bind neither moving the new value... just removing de bind line did the trick.
If i find something new about the topic i'll post it here beacause it still doesn't feel quite right.
Anyway, thanks again,
Omar