BeanFieldGroup fields not updating

I am new to vaadin so excuse me if this is a stupid question.

I am making a simple application with vaadin cdi.
I have a tree with items on it, when you select a node on the tree an event fires which updates a backing bean.
The fields which display the backing bean values is constructed with BeanFieldGroup. Initially when the fieldgroup is created the values are displayed fine but when the tree selection event fires and changes the backing bean the values in the UI fields do not get updated.

  beanFieldGroup = new BeanFieldGroup(TimeAction.class);
  beanFieldGroup.setBuffered(false);
  beanFieldGroup.bindMemberFields(timeAction);

  client = beanFieldGroup.buildAndBind("Client", "timeMast.timemast_client.clientName", TextField.class);
  client.setReadOnly(true);
  client.setImmediate(true);

  layout.addComponent(client);
  beanFieldGroup.setItemDataSource(timeAction);

Do I need to reperform All of the above code anytime a backing value changes?

It doesn’t seem that the getters for the bean properties fire after initial binding. Also the setReadonly(true) doesn’t have any effect.

still strugglin with this any help is appreciated

Hi,

I think the problem is that you’re directly updating the bean value. Because there’s no facilities in Java to listen to arbitrary property changes, there’s no way for Vaadin to realize something has changed and propagate the change to the UI. What you can do is create a BeanItem wrapper yourself, set that as the BeanFieldGroup datasource and update the bean through it:

    BeanItem timeActionItem = new BeanItem(timeAction);
    beanFieldGroup.setItemDataSource(timeActionItem);

    // in your selection event listener
    timeActionItem.getProperty("yourPropertyName").setValue(someNewValue);

Or if you want to change the whole backing bean in the selection listener, just call
beanFieldGroup.setItemDataSource(anotherBean)
. I think your
beanFieldGroup.bindMemberFields(timeAction)
is unnecessary/erroneous;
bindMemberFields
is meant for the use case where you have an object containing a bunch of Vaadin fields and want to use them instead of doing eg.
buildAndBind
.

What you are saying makes sense. I am coming from JSF where binding means that changes to the display are propogated to backing bean and vice versa every request/response.

I looked at using BeanItem’s but I have nested backing beans “timeMast.timemast_client.clientName” and it doesn’t seem like BeanItem can handle that case? Unless I missed something
FYI
timeMast.timemast_client might be null then set to something without timeMast ever changing.

Update:
I just notices the
addNestedProperty method of BeanItem. That should do the trick. Thanks for your time!

    public void update(@Observes TreeSelectEvent tmue) {
        beanFieldGroup.setItemDataSource(timeMastItem);
    }
    @Override
    public void itemClick(ItemClickEvent event) {
        Item item = event.getItem();
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) item.getItemProperty("treeNode").getValue();
        events.fire(new TreeSelectEvent(node));        
        beanFieldGroup.setItemDataSource(timeMastItem);
    }

I converted to use BeanItem wrapper with NestedMethodProperty to add items. However I do not think that was my main point of pain (I tried many implementations before posting).

Anyway, I am using Vaadin CDI; In the above code setting the beanFieldGroup.setItemDataSource from within the itemClick method behaves properly ie the UI gets updated with new values from the backing bean. But, if I do the same thing from an observer method. Nothing happens.

Maybe this is a bug in the CDI plugin? or maybe this isn’t supposed to work? I would like to propogate UI Events into CDI Events for various reasons but if they can’t interact properly with the UI it doesn’t make much sense.

Also why does setting the datasource change All the Field’s readonly property?

Hi everybody,
even if this post is already from 2 years ago: I just faced a similiar issue, that setItemDataSource on a BeanFieldGroup didn’t work for me, when I did this driven by an event mechanism like in the example before. So I checked on which instances of my component I worked. And bingo: there were 2, so I changed scope of my CustomComponent to @SessionScoped and now it works.