combobox submitting wrong data on form submit

Hey there,

I’ve got a combobox with a jpa-container as it’s datasource. The class of the container contains only id (Long) and name (String).

I’ve got the combobox displaying the name instead the id by:

combo.setItemCaptionPropertyId(“name”);

Is there a possibility to tell the combobox which value (id or name) to submit on form submit?

My problem is:
I’ve got 2 classes, user and group. A user can only be member of one group.
I display a table (which has another jpa-container as it’s source) containing the users with its associated group.

When clicking the table I display a edit form with user data and a combox containing the groups.

But when changing the group in my combobox the table (and database) displays the id of the new chosen group instead of the name, also a new group is being inserted into the database named as the id of the chosen group.

Any hints on this?

Thanks

Hi Kersten,

I guess the id you see is a foreign key to another table. Isn’t there own table for your Group object? (I don’t know the exact class name but let’s say now it is ‘Group’)

The value of ComboBox is the Group object not just the id or name. So, I think your problem is just that you should change your table to show ‘name’ instead of ‘id’.

One way to do this is to overwrite the ‘formatPropertyValue’ method of the table:


        Table table = new Table(){
        @Override
        protected String formatPropertyValue(Object rowId, Object colId,Property property) {
                            Object v = property.getValue();
                            if (v instanceof Group) {
                                return v.getName();
                            }
                            return super.formatPropertyValue(rowId, colId, property);
                        }
            
               };

I was just guessing so if this does not help could you please show your code. At least, the lines where you create your table and combobox objects.

Thanks for your reply!

Tables are automatically generated from my classes:

Table benutzer: id, vorname, nachname, fachbereich_id
Table fachbereich: id, name

Here’s my code:

EntityManagerFactory factory = Persistence.createEntityManagerFactory("xxxPU");
        final EntityManager em = factory.createEntityManager();

        MutableLocalEntityProvider<Benutzer> myEntityProvider = new MutableLocalEntityProvider<Benutzer>(Benutzer.class, em);
        MutableLocalEntityProvider<Fachbereich> fbMyEntityProvider = new MutableLocalEntityProvider<Fachbereich>(Fachbereich.class, em);

        final EntityContainer<Benutzer> container = new JPAContainer<Benutzer>(Benutzer.class);
        container.setEntityProvider(myEntityProvider);

        final EntityContainer<Fachbereich> fbContainer = new JPAContainer<Fachbereich>(Fachbereich.class);
        fbContainer.setEntityProvider(fbMyEntityProvider);
...
table.setContainerDataSource(container);
table.setVisibleColumns(new String[]{"id", "vorname", "nachname", "fachbereich"});
table.addListener(new Table.ValueChangeListener() {

            public void valueChange(ValueChangeEvent event) {
                Object value = event.getProperty().getValue();
                if (value != null) {
                    EntityItem<Benutzer> benutzerItem = container.getItem(event.getProperty().getValue());
                    benutzerForm.setItemDataSource(benutzerItem);
                    benutzerForm.setVisibleItemProperties(new String[]{"vorname", "nachname", "fachbereich"});
                    Item item = table.getItem(value);
                    
                    if (item.getItemProperty("fachbereich").getValue() != null) {
                        combo.setValue(benutzerItem.getEntity().getFachbereich().getId());
                    }

                    benutzerForm.getFooter().removeAllComponents();
                    mainWindow.addComponent(benutzerForm);
                     benutzerForm.getFooter().addComponent(apply);
                } else {
                    mainWindow.removeComponent(benutzerForm);
                }
            }
        });
...

final Form benutzerForm = new Form();

        final Button apply = new Button("Save", new Button.ClickListener() {

            public void buttonClick(ClickEvent event) {
                try {
                    benutzerForm.commit();
                } catch (Exception e) {
                    // Ignored, we'll let the Form handle the errors
                }
            }
        });
...

final ComboBox combo = new ComboBox("Fachbereich");
        combo.setContainerDataSource(fbContainer);
        combo.setItemCaptionPropertyId("name");
        combo.setNullSelectionAllowed(false);
        combo.setImmediate(true);

        benutzerForm.setItemDataSource(benutzerItem); // bind to POJO via BeanItem
        benutzerForm.setVisibleItemProperties(new String[]{"vorname", "nachname", "fachbereich"});


        benutzerForm.setFormFieldFactory(new FormFieldFactory() {

            @Override
            public Field createField(Item item, Object propertyId, Component uiContext) {
                Field field = DefaultFieldFactory.get().createField(item, propertyId, uiContext);

                if ("vorname".equals(propertyId)) {
                    TextField tf = (TextField) field;
                    tf.setNullRepresentation("");
                    tf.setRequired(true);
                    tf.setRequiredError("Please enter a First Name");
                    tf.addValidator(new StringLengthValidator("First Name must be 3-25 characters", 3, 25, false));
                } else if ("nachname".equals(propertyId)) {
                    TextField tf = (TextField) field;
                    tf.setNullRepresentation("");
                    tf.setRequired(true);
                    tf.setRequiredError("Please enter a Last Name");
                    tf.addValidator(new StringLengthValidator("Last Name must be 3-50 characters", 3, 50, false));
                } else if ("fachbereich".equals(propertyId)) {
                    return combo;
                }
                return field;
            }
        });


@Entity
public class Fachbereich implements Serializable {

...
    
    @OneToMany(mappedBy = "fachbereich", cascade={CascadeType.PERSIST, CascadeType.MERGE})
    private List<Benutzer> benutzerliste;
    
    @Id
    @GeneratedValue
    private Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
...

@Entity
public class Benutzer implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

...
    
    @ManyToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE})
    private Fachbereich fachbereich;

    /**
     * @return the fachbereich
     */
    public Fachbereich getFachbereich() {
        return fachbereich;
    }

    /**
     * @param fachbereich the fachbereich to set
     */
    public void setFachbereich(Fachbereich fachbereich) {
        this.fachbereich = fachbereich;
    }
...

Your code seemed logical to me but didn’t work for some reason.

My Table displays all “Fachbereichs” correctly (I mean the name, not id) upon starting the application. But hitting apply creates a new “Fachbereich” named (name) like the id of the chosen “Fachbereich” in my edit form.

Thanks a lot!

Ok. I was wrong. The value of ComboBox is the item identifier not the item. In this case, it’s the id of the entity (with BeanItemContainer, it would be the bean itself). You could look the demo of JPAContainer. ComboBox is used there.

Does the combobox create a new instance of Fachbereich i.e. it has new id but the name is the same as some other instances id?

You could probably make a workaround with nested properties or override the getValue() method of ComboBox.

Or you can use BeanFieldWrapper/FieldWrapper in the
CustomField add-on
to do the conversions.