Search code examples
javavaadin7

BeanFieldGroup with ComboBox?


I'm trying create a ComboBox component using BeanFieldGroup in my application, but still can't do this works. I tried create a combobox first and after add this combobox in buildAndBind but doesn't work also.

I'm trying this:

/** person's bean */
@Entity
public class Person{

@Id
@GeneratedValue
private Integer id;

@NotNull
@NotEmpty
@Size(min=5, max=50, message="insert first name")
private String firstName;

@NotNull
@NotEmpty
@Email private String email;

//female or male
private String gender;

//get and set
}

/** app */
public class PersonView extends CustomComponent{
private final BeanFieldGroup<Person> binder = new BeanFieldGroup<Person>(Person.class);
private Person bean = new Person();

    private ComboBox gender;

    public PersonView(){
         VerticalLayout vLayout = new VerticalLayout();
         Field<?> field = null;
         field = binder.buildAndBind("Gender", "gender", ComboBox.class);
         gender = (ComboBox)binder.getField("gender");
         gender.addItem("Male");
         gender.addItem("Female");
         vLayout.addComponent(gender);
    }
}

Exception:

/** exception /*
Caused by: com.vaadin.data.fieldgroup.FieldGroup$BindException: Unable to build a field of type com.vaadin.ui.ComboBox for editing java.lang.String
    at com.vaadin.data.fieldgroup.FieldGroup.build(FieldGroup.java:1067)
    at com.vaadin.data.fieldgroup.FieldGroup.buildAndBind(FieldGroup.java:1039)
    at br.ind.ibg.views.CurriculumView.buildLayout(CurriculumView.java:50)
    at br.ind.ibg.views.CurriculumView.<init>(CurriculumView.java:32)
    at br.ind.ibg.views.LoginView.buttonClick(LoginView.java:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:508)
    ... 37 more

How I do this ?


Solution

  • Thats a good question! After some investigation I found the following solution:

    You have to create your custom FieldGroupFieldFactory (why see below):

    binder.setFieldFactory(new DefaultFieldGroupFieldFactory() {
    
        @Override
        public <T extends Field> T createField(Class<?> type, Class<T> fieldType) {
    
            if (type.isAssignableFrom(String.class) && fieldType.isAssignableFrom(ComboBox.class)) {
                return (T) new ComboBox();
            }
    
            return super.createField(type, fieldType);
        }
    
    });
    

    The reason why:

    If you have a look at the vaadin source code of DefaultFieldGroupFieldFactory.java you will see that in the end a ComboBox will only be created IF you provide an Enum as "property data source". You provide a String so the DefaultFieldGroupFieldFactory wants to create a TextField. But you provided a ComboBox. In the end there is an Exception thrown.

    With your own Factory it will work. Don't forget to setItemDataSource(bean) and commit() your binder to actually write the gender to the bean.