Updating after data binding does not update content in UI

Hi all,

Sorry, but I must have a mental lapsus right now, because I don’t see where the problem is, and should be trivial. I’ve prepared a simple scenario where I bind a field to a bean property using the BeanFieldGroup, and when I click the Change and Reset buttons, the model is set with the correct values, but the textfield in the UI is not being updated.
I’m using Vaadin4Spring, but should not be the issue. The view is properly rendered.

import com.vaadin.data.fieldgroup.BeanFieldGroup;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener;
import com.vaadin.spring.annotation.SpringView;
import com.vaadin.ui.Button;
import com.vaadin.ui.Notification;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import java.io.Serializable; 
[/code][code]
@SpringView(name = "test")
public class TestView extends VerticalLayout implements View {
private TextField txtTest = new TextField("Test");
private Button btnChange = new Button("Click!");
private Button btnReset = new Button("Reset");
private TestBean testBean = new TestBean();
public TestView() {
    txtTest.setImmediate(true);
    addComponent(txtTest);
    addComponent(btnChange);
    addComponent(btnReset);
    BeanFieldGroup<TestBean> binder = new BeanFieldGroup<>(TestBean.class);
    binder.setItemDataSource(testBean);
    binder.setBuffered(false);
    binder.bind(txtTest, "text");
    initComponents();
}

private void initComponents() {
    btnChange.addClickListener(new Button.ClickListener() {
        @Override public void buttonClick(Button.ClickEvent event) {
            testBean.setText("Hello world!");
        }
    });
    btnReset.addClickListener(new Button.ClickListener() {
        @Override public void buttonClick(Button.ClickEvent event) {
            testBean.setText("");
        }
    });
}

@Override public void enter(ViewChangeListener.ViewChangeEvent event) {
    Notification.show("Test");
}

public class TestBean implements Serializable {
    private String text;
    public TestBean() { text = ""; }
    public String getText() { return text; }
    public void setText(String text) { this.text = text; }
}

}

If you modify beans directly, the bound Vaadin fields will not know about the modifications. You need to modify them through the item/container interface with setValue().

Well, you could also notify the Vaadin fields about the modifications, but the notification mechanism is rather a lot extra to do. There’s an
example here
. However, I don’t really know if such mechanism is often or ever needed in real applications.

Hi Marko, thanks for the quick reply.
It is working now, as you proposed, with setting the BeanItem property directly with the “setValue” method, but immediately a question comes to my mind.

For instance, I’m using right now beanItem.getItemProperty("text").setValue("Hello World!"); Is there any way to avoid checking the property names every time in the wrapped beans? Isn’t this very error prone?
Do I always need to know that the property is spelled “text”, with no autocompletion in this area? What do developers usually do as a best practice here? Having this wrapped object with an Enumeration with all property names to avoid errors?

Thanks again

Fran

That’s a good question. I don’t really know what the best practice would be, other than enumeration (with constants) as you suggested, as there isn’t any really good way to have property identifiers in Java. Using constants would at least encapsulate the identifiers in the beans itself, so you wouldn’t need to use strings in other code. And it’s simple to do.

If you use CDI or Spring to manage the beans, you could perhaps use their notification or other mechanisms to notify Vaadin about changes to the beans. That would obviously be restricted to managed beans, and perhaps be more complex than what you’re looking for.

I started thinking if you could use method references in Java 8 to do some tricks, like the following:

SomeDataUtil.setValue(beanItem, MyBean::setText, "Hello World!"); However, apparently that’s
not quite possible
, even though there could be
some really tricky way to do it
.

Thanks for the reply.
I can live with the current situation. It just would be much simpler if there was something like GWT Pectin library for double data-binding.
Have a nice day Marko

Fran

(You could also use something like CGILib to develop a proxy that intercepted all set operations, and generated Notifications)

If I modify beans “past” Item/Property interface (which I do quite often), I just tend to rebind/refresh my data in forms or Table/Grid. I know the places where that happen (typically in save action) so it is very easy to just notify those parts of application that are interested of that. At least much easier than to live with string keys and Container-Item-Property interfaces. This approach might cause a bit more of the UI to be redrawn, but the effect is not that dramatic. Using something like CDI events is excellent for this kind of things.

If I’d really want to automatise the changes to elsewhere, I’d indeed consider something like Charles suggeted. I have had a plan to try
ByteBuddy
, which is a fresh start for code generation. Maybe it could dynamically implement Item/Property stuff or domain objects? Something to be investigated in the future.

cheers,
matti