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:

[code]
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…)
}
};
}
}
[/code]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