Table.iterator().next() gives an unpredictable result

I want to set first focusable component of my editable table in a focus. Like this:

import javax.servlet.annotation.WebServlet;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Table;
import com.vaadin.ui.Tree;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;

@Theme(ValoTheme.THEME_NAME)
@SuppressWarnings("serial")
public class MyVaadinUI extends UI {

    @WebServlet(value = "/*", asyncSupported = true)
    @VaadinServletConfiguration(productionMode = false, ui = MyVaadinUI.class)
    public static class Servlet extends VaadinServlet {
    }

    @Override
    protected void init( VaadinRequest request ) {
        final VerticalLayout layout = new VerticalLayout();
        setContent( layout );

        Table table = new Table( "Table" );
        for (String prop : new String { "p1" , "p2", "p3", "p4", "p5"}) {
            table.addContainerProperty( prop, Integer.class, null );
        }
        for (int row = 1; row <= 5; row++) {
            table.addItem( new Object { row, row*2, row*3, row*4, row*5 }, row );
        }
        table.setEditable( true );
        
        layout.addComponents( table );
        
        // focus first component
        ((Focusable) table.iterator().next()).focus();
    }
}

But table.iterator().next() gives an unpredictable result.

Is it a bug?

Thanks.

Hello,

If you dive into code you’ll see table’s iterator() method returns visibleComponents.iterator(). visibleComponents in turn is a HashSet, and it’s commented as follows:

/**
 * Returns an iterator over the elements in this set.  The elements
 * are returned in no particular order.
 *
 * @return an Iterator over the elements in this set
 * @see ConcurrentModificationException
 */
public Iterator<E> iterator() {
  return map.keySet().iterator();
}

Hello,

Exactly. I dived into Table class code:

        if (replaceListeners) {
            // initialize the listener collections, this should only be done if
            // the entire cache is refreshed (through refreshRenderedCells)
            listenedProperties = new HashSet<Property<?>>();
            visibleComponents = new HashSet<Component>();
        }

Private field visibleComponents must be initialized as
new LinkedHashSet()
.
In my opinion it’s a bug.

Well, it depends. The
HasComponents.iterator()
contract does not promise any particular iteration order, and especially in case of components other than layouts it is intended mostly for internal bookkeeping of the hierarchy. Table is sort of a special case, in Vaadin 6 it didn’t have any API for accessing components in its cells, and the Vaadin 7 API is barebones meant to just make the framework itself work. Still, it would be useful if the iteration order were not unspecified, but note that LinkedHashSet is not going to cut it at the moment someone decides to add rows to somewhere else than the end…

In my opinion, more expected behavior of
HasComponents.iterator()
contract is to get components in
natural
order.
In my case, initializing
visibleComponents
as
LinkedHashSet
is a solution of the problem. Unfortunately, i can’t to override any code to solve this problem. No way to do it.

By the way, add rows to a table involves a complete rebuilding of visibleComponents collection. Сall stack:
containerItemSetChange( … )
refreshRowCache()
refreshRenderedCells()
getVisibleCellsNoCache(firstIndex, rows, true)
visibleComponents = new HashSet();