Grid addRow() when Filter has Text -> throws NullPointerException

If the filter does not have any text there is no NullPointerException.

I am calling addRow() after resultsGrid.getContainerDataSource().removeAllItems(); is called. I am repopulating the grid from the database to reflect new changes.

Hi,

I was unable to reproduce this bug. Can you show a piece of code that triggers the NPE? What container you are using? What kind of Filter?

From a quick go-through of the related methods I did not spot any location which should cause the problem.

//Teemu

Below is a component with full code that will reproduce the error. (null pointer is created at line 5604 in the Grid.class)

The same code is attached as a file too.

package com.widgets;

import com.vaadin.data.util.GeneratedPropertyContainer;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.data.util.filter.SimpleStringFilter;
import com.vaadin.server.Responsive;
import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.HeaderCell;
import com.vaadin.ui.Grid.HeaderRow;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;

public class GridFilterNull extends VerticalLayout {
    
    private static final long serialVersionUID = -8367212819731798521L;

    CssLayout panelWrap = new CssLayout();
    
    Panel resultsPanel = new Panel("Search Results");
    VerticalLayout resultsPanelLayout = new VerticalLayout();
        
    Panel personPanel = new Panel("Person");
    VerticalLayout personPanelLayout = new VerticalLayout();
    HorizontalLayout person_ctrl = new HorizontalLayout();
    Label label_name = new Label("<h3><em>Please select row above...</em></h3>", ContentMode.HTML);
    Button view_apps = new Button("Applications");
    Button view_event_roles = new Button("Event Roles");
    Button view_visits = new Button("Visits");
    Label html_hr = new Label("<hr />", ContentMode.HTML);
    HorizontalLayout updatePerson = new HorizontalLayout();
    
    IndexedContainer container = new IndexedContainer();
    GeneratedPropertyContainer gpcontainer = new GeneratedPropertyContainer(container);
    Grid resultsGrid = new Grid();
    
    Button refreshPopGrid = new Button("Refresh Pop Grid", e -> populateGrid());
    
    
    public GridFilterNull() {
        
        //Grid Container
        container.addContainerProperty("person_id", String.class, null);
        container.addContainerProperty("firstname", String.class, null);
        container.addContainerProperty("lastname", String.class, null);
        container.addContainerProperty("email", String.class, null);
        container.addContainerProperty("role", String.class, null);
        
        gpcontainer = new GeneratedPropertyContainer(container);
        
        resultsGrid.setContainerDataSource(gpcontainer);
        resultsGrid.setSelectionMode(Grid.SelectionMode.SINGLE);
        
        //Gets designated column value from row selection
        resultsGrid.addItemClickListener(e -> personSelect((String) e.getItem().getItemProperty("person_id").getValue(),
                (String) e.getItem().getItemProperty("firstname").getValue() + " " + (String) e.getItem().getItemProperty("lastname").getValue()));
        
        //Set Column header names
        resultsGrid.getColumn("person_id").setHeaderCaption("Person ID").setWidth(100);
        resultsGrid.getColumn("firstname").setHeaderCaption("First Name");
        resultsGrid.getColumn("lastname").setHeaderCaption("Last Name");
        resultsGrid.getColumn("email").setHeaderCaption("Email");
        resultsGrid.getColumn("role").setHeaderCaption("System Role").setWidth(200);
        ///////////////////////////////////////////////////////////////////////////////
        
        setSpacing(false);
        setMargin(false);
        
        // panel & panelLayout
        this.addComponent(panelWrap);
        panelWrap.setWidth("100%");
        panelWrap.addStyleName("panelWrap");
        Responsive.makeResponsive(panelWrap);
        panelWrap.addStyleName("panel-padding");
        
        //results panel from search
        panelWrap.addComponent(resultsPanel);
        resultsPanel.setWidth("100%");
        resultsPanel.setContent(resultsPanelLayout);
        resultsPanelLayout.setMargin(true);
        resultsPanelLayout.setSpacing(true);
        
        resultsPanelLayout.addComponent(resultsGrid);
        resultsGrid.setWidth("100%");
        resultsGrid.setHeightMode(HeightMode.ROW);
        resultsGrid.setHeightByRows(8);
        
        panelWrap.addComponent(personPanel);        
        personPanel.setWidth("100%");
        personPanel.setContent(personPanelLayout);
        personPanelLayout.setSpacing(false);
        Responsive.makeResponsive(personPanelLayout);
        
        HorizontalLayout buttons = new HorizontalLayout();
        buttons.setMargin(false);
        buttons.setSpacing(true);
        buttons.addComponents(refreshPopGrid);
        Responsive.makeResponsive(buttons);
        
        HorizontalLayout person_sel = new HorizontalLayout();
        person_sel.setMargin(false);
        person_sel.setSpacing(true);
        person_sel.setWidth("80%");
        person_sel.addComponents(label_name);
        
        person_ctrl.setWidth("100%");
        person_ctrl.setMargin(true);
        person_ctrl.addComponents(person_sel, buttons);
        person_ctrl.setComponentAlignment(person_sel, Alignment.TOP_LEFT);
        person_ctrl.setComponentAlignment(buttons, Alignment.TOP_RIGHT);
        Responsive.makeResponsive(person_ctrl);
        personPanelLayout.addComponent(person_ctrl);
        
        //adds filters to grid
        addFilters();
        
        //populate grid
        populateGrid();
    }

    public void personSelect(String person_id, String name) {
        label_name.setValue("<h3><em>" + name + "</em></h3>");
    }
    
    public void addFilters() {
        // Create a header row to hold column filters
        HeaderRow filterRow = resultsGrid.appendHeaderRow();
        
        // Set up a filter for all columns
        for (Object pid: resultsGrid.getContainerDataSource().getContainerPropertyIds()) {
            HeaderCell cell = filterRow.getCell(pid);
            TextField filterField = new TextField();
            
            filterField.setInputPrompt("Filter");
            filterField.addStyleName(ValoTheme.TEXTFIELD_TINY);
            
            // Update filter When the filter input is changed
            filterField.addTextChangeListener(change -> {
                // Can't modify filters so need to replace
                container.removeContainerFilters(pid);

                // (Re)create the filter if necessary
                if (! change.getText().isEmpty())
                    container.addContainerFilter(new SimpleStringFilter(pid,change.getText(), true, false));
            });
            cell.setComponent(filterField);
        }
    }
    
    public void populateGrid() {
        //clears grid data from grid datasource
        resultsGrid.getContainerDataSource().removeAllItems();
        
        //normally there is MySQLfunction that pulls a massive list of people
        resultsGrid.addRow("1", "John", "Smith", "js@grid.com", "User");
        resultsGrid.addRow("2", "Sam", "Tarley", "st@grid.com", "User");
        resultsGrid.addRow("3", "Tina", "Sousa", "ts@grid.com", "Admin");
        resultsGrid.addRow("4", "Murphy", "Watson", "mw@grid.com", "Admin");
        resultsGrid.addRow("5", "Finn", "Brien", "fb@grid.com", "User");
        resultsGrid.addRow("6", "Alison", "Wallace", "aw@grid.com", "User");
        resultsGrid.addRow("7", "James", "Reynolds", "jr@grid.com", "Admin");
        resultsGrid.addRow("8", "Don", "Williams", "dw@grid.com", "User");
    }
}

21067.java (6.49 KB)

Hello,

The issue is not related to Grid specifically but a faulty behaviour in GeneratedPropertyContainer. The underlying container returns null on adding the item and thus leads into a null pointer exception when the item is attempted to access. I posted a ticket for this at https://dev.vaadin.com/ticket/18685 . Thank you for noticing!

//Teemu

Thanks Teemu! I have been trying to find ways to modify the filters for a temporary workaround. No success yet. Will try to work with the container as well.