TwinColSelect: default selected value?

Folks, how to set a default value for a TwinColSelect? When I do twin.setValue(unmodifiableSetHere) — it really dislikes it, spitting into the browser a pile of binary characters…


Update: Wed May 26 06:01:11 UTC 2010

Uh huh… A pitfall:
setValue
should be
before
listener sat, because setValue also triggers getValue, which renders to a java.lang.NullPointerException — anyone please maybe put
synchronized
there at the moment when datasource gets changed?. E.g. this will fail:


    private TwinColSelect someTwinSelect;

    someTwinSelect.addListener(new ValueChangeListener() {
            @Override
            public void valueChange(ValueChangeEvent event) {
                SomeWindow.this.currentTwinSelectValue = SomeWindow.this.someTwinSelect.getValue();
            }
    });

    HashSet defaults = new HashSet();
    defaults.add(someObject);

    // This will crash everything miserably
    this.someTwinSelect.setValue(Collections.unmodifiableSet(defaults));

…but this will work fine:


    private TwinColSelect someTwinSelect;

    HashSet defaults = new HashSet();
    defaults.add(someObject);
    this.someTwinSelect.setValue(Collections.unmodifiableSet(defaults));

    someTwinSelect.addListener(new ValueChangeListener() {
            @Override
            public void valueChange(ValueChangeEvent event) {
                SomeWindow.this.currentTwinSelectValue = SomeWindow.this.someTwinSelect.getValue();
            }
    });

So if you want to set the values
again
after application has been inited, then… what? Should I use some semaphores/flags to disable valueChange while setting default value? :grin:

You could try to remove the listener always before you set the default value, and then add it back again after the value is set, i.e.

ValueChangeListener myListener = new ValueChangeListener() {
    @Override
    public void valueChange(ValueChangeEvent event) {
       SomeWindow.this.currentTwinSelectValue = SomeWindow.this.someTwinSelect.getValue();
    }
}

...

this.someTwinSelect.removeListener(myListener);
this.someTwinSelect.setValue(Collections.unmodifiableSet(defaults));
this.someTwinSelect.addListener(myListener);

Well, yes, that’s exactly what I am saying: either you remove that listener or disable it on the moment you set the value. It works for me now though, but the point is that there must be some way to set it without such a quite ugly dance, I think.

getValue() having side effects is VERY ugly. Why it hasn’t been fixed, IIRC, is that a proper fix would break some API - but I hope it gets fixed in Vaadin 7. I had the recollection there would already be a ticket for this, but could not find it.

As for synchronization, I don’t see any point in it - I don’t think the issue is accessing something from a background thread, and Vaadin API is not thread safe anyway unless you synchronize access to components to your Application.

Could you
create a ticket
about getValue() side effects, and if that is not enough to solve the issue, one about setValue() causing problems when there is a listener (with a little test case)?

To be honest, synchronization thing I said before I looked at the code. :slight_smile: Now, after I did, I totally agree with you on that: no point indeed. Very ugly: another agree. Looks like it triggered by itself, hence goes like infinite loop, but fails because of null exception. It should be anyhow there like one-after-another (that was my initial idea about sync, but just I see it is not working this way at all).

Ticket: sure. This should be definitely noted.