Vaadin 8.1.0 rc1 + Grid problem

Hi!

I’m moving from Java and Vaadin 7.7 to vaadin-on-kotlin framework. The problem that I have is not a vaadin-on-kotlin specific, but it’s more specific to Grid component and editing values there…

The problem is that when I open the view, it lists all the rows correctly with correct data. Filters and sorting also works perfectly. But when I try to edit anything, I get the exception:

10:03:03.833 [qtp279680875-909] ERROR c.vaadin.server.DefaultErrorHandler - java.lang.IllegalStateException: Duplicate key Person(firstName=matti222, lastName=meikalainen22, sotu=111111) at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133) at java.util.HashMap.merge(HashMap.java:1245) at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320) at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1540) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at com.vaadin.data.provider.DataCommunicator$ActiveDataHandler.getActiveData(DataCommunicator.java:165) at com.vaadin.data.provider.DataCommunicator.refresh(DataCommunicator.java:521) at com.vaadin.ui.AbstractListing$AbstractListingExtension.refresh(AbstractListing.java:122) at com.vaadin.ui.components.grid.EditorImpl.save(EditorImpl.java:250) at com.vaadin.ui.components.grid.EditorImpl$1.save(EditorImpl.java:133) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:155) at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:116) at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:445) at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:410) at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274) at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90) at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41) at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1577) at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:381) at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669) at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:224) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at org.eclipse.jetty.server.Server.handle(Server.java:499) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257) at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555) at java.lang.Thread.run(Thread.java:745) and here is the code(written in kotlin), that I’m using:

@AutoView("")
class TestView: VerticalLayout(), View {


    private lateinit  var personGrid: Grid<Person>
    private lateinit  var firstNameFilter: TextField
    var persons = listOf<Person>(Person(1, "matti", "meikalainen", "111111"), Person(2, "teppo", "testaajaa", "2222222"))

    companion object {
        fun navigateTo() = navigateToView<WelcomeView>()
    }

    init {

        var personsListProvider = ListDataProvider<Person>(persons).withConfigurableFilter()
      

        isMargin = false
        label("Vaadin On Kotlin testview") {
            w = fillParent
            addStyleNames(ValoTheme.LABEL_H1, ValoTheme.LABEL_COLORED)
        }



        personGrid = grid(Person::class, "List of Persons", personsListProvider) {
            setItems(persons)
            expandRatio = 1f;
            setSizeFull()

            val binder: Binder<Person> = getEditor().getBinder()


            column(Person::firstName) {
                caption="firstname"
                setEditorComponent(TextField("firstname"), Person::firstName.setter)
               isEditable = true
                isHidden = false
            }




            column(Person::lastName) {
                setEditorComponent(TextField("lastname"), Person::lastName.setter)
                isEditable = true
            }

            column(Person::sotu) {
                setEditorComponent(TextField("sotu"), Person::sotu.setter)
                isEditable = true

            }

            editor.addCancelListener( { event -> Notification.show("Editing Cancelled...")
            } )
            editor.addSaveListener({ event ->
                Notification.show("Saving ${event.bean.firstName} - ${event.bean.lastName} - ${event.bean.sotu} -...")
                binder.writeBean(event.bean)

                //personsListProvider.refreshAll()

                // just for debugging to see what's in the provider now..
                /*personsListProvider.getAll().forEach(
                        {
                            println("${it.firstName} - ${it.lastName} - ${it.sotu}")
                        }
                )*/

                refresh()

            })

            editor.setSaveCaption("Tallenna")
            editor.setCancelCaption("Peruuta")

            editor.setEnabled(true)

            addColumn({ "Show" }, ButtonRenderer<Person>({ event -> personGrid.refresh() }))
            addColumn({ "Edit" }, ButtonRenderer<Person>({ event -> null }))
            addColumn({ "Delete" }, ButtonRenderer<Person>({ event -> null }))

            // automatically create filters, based on the types of values present in particular columns.
            appendHeaderRow().generateFilterComponents(this, Person::class)


        }

        personGrid.addItemClickListener({ event -> Notification.show("Value: " + event.getItem()) })

    }




    override fun enter(event: ViewChangeListener.ViewChangeEvent?) {
        personGrid.dataProvider.refreshAll()
    }

}

I was starting to think, that is this a bug in Grid or am I really doing something wrong?

More discussion is here also.
https://github.com/mvysny/vaadin-on-kotlin/issues/6

I have the same issue and have posted also to the bug report at: https://github.com/vaadin/framework/issues/9678.
In-cell editing often works for me, but the exception is raised typically after a few edits are done, after the save button is pushed. I have not been able to repeat the error reliably yet.

FWIW, my environment is a little different:

java version 1.8.0_141
Tomcat 8.5.19
Vaadin 8.1.0

Aug 01, 2017 5:30:36 PM com.vaadin.server.DefaultErrorHandler doDefault
SEVERE: 
java.lang.IllegalStateException: Duplicate key {doneat=5749.6, log4=0, log5=1, worktype=Inspection, description=Phase C / 50hr On-condition inspection, workdone=Tightened fuel cap, doneon=2017-05-30 16:43:29.0, workordernumber=14, planeid=1377035000007, log2=0, complete=1, log3=1, maintid=1495120791323, log1=1}
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1253)
at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1548)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.vaadin.data.provider.DataCommunicator$ActiveDataHandler.getActiveData(DataCommunicator.java:165)
at com.vaadin.data.provider.DataCommunicator.refresh(DataCommunicator.java:521)
at com.vaadin.ui.AbstractListing$AbstractListingExtension.refresh(AbstractListing.java:122)
at com.vaadin.ui.components.grid.EditorImpl.save(EditorImpl.java:250)
at com.vaadin.ui.components.grid.EditorImpl$1.save(EditorImpl.java:133)
at sun.reflect.GeneratedMethodAccessor39.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:155)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:116)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:445)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:410)
at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)
at com.vaadin.server.communication.PushHandler.lambda$new$1(PushHandler.java:145)
at com.vaadin.server.communication.PushHandler.callWithUi(PushHandler.java:235)
at com.vaadin.server.communication.PushHandler.onMessage(PushHandler.java:520)
at com.vaadin.server.communication.PushAtmosphereHandler.onMessage(PushAtmosphereHandler.java:87)
at com.vaadin.server.communication.PushAtmosphereHandler.onRequest(PushAtmosphereHandler.java:77)
at org.atmosphere.cpr.AsynchronousProcessor.action(AsynchronousProcessor.java:223)
at org.atmosphere.cpr.AsynchronousProcessor.suspended(AsynchronousProcessor.java:115)
at org.atmosphere.container.Servlet30CometSupport.service(Servlet30CometSupport.java:67)
at org.atmosphere.cpr.AtmosphereFramework.doCometSupport(AtmosphereFramework.java:2284)
at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:593)
at org.atmosphere.websocket.DefaultWebSocketProcessor$3.run(DefaultWebSocketProcessor.java:345)
at org.atmosphere.util.VoidExecutorService.execute(VoidExecutorService.java:101)
at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:340)
at org.atmosphere.websocket.DefaultWebSocketProcessor.invokeWebSocketProtocol(DefaultWebSocketProcessor.java:447)
at org.atmosphere.container.JSR356Endpoint$3.onMessage(JSR356Endpoint.java:272)
at org.atmosphere.container.JSR356Endpoint$3.onMessage(JSR356Endpoint.java:269)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395)
at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119)
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133)
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82)
at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171)
at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148)
at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)

Hi Steve,

Do you have a more or less minimal Java example? I had some issues with Kotlin to begin with, so couldn’t really test the earlier example. It would be great if I got an example UI where this happens consistently, so I can understand what goes wrong, where and why.

//Teemu

My grids are all quite complex, derived from a base class that extends Grid, subclasses that implement grid-specific stuff, a helper class that provides filtering and rendering services and data management classes that organize the database calls. It would be a challenge to make a simple case that also has the offending characteristic.

I will look into Eclipse Oxygen’s portfolio of debugging tools to see if I can shed some light that way. And I would be happy to let a Vaadin person into my system. The fault is easy to reproduce, but not due to any particular sequence of steps.

I’ll try to make some progress and will return with any findings.

I’m going to declare this one my fault. I think. The problem related to my making changes to bean properties (HashMap values in my case) from inside grid components’ change listeners. It seems that my changes interfered with Grid’s manipulation of the same data.

The root cause stems from not knowing the most effective and efficient way of refreshing a grid, along with all of its data, selectons and internal components, after making a change. Often I would interact with a component in a grid (tick a CheckBox for example) and have that action properly recorded to the database. But the tick would disappear when the row selection changes. The problem is solved with full grid refreshes on every change, but that’s heavy. Changes that require re-selections to occur have to wait (or be queued by) the dataprovider call otherwise the re-selections are eliminated by the data refresh. I have not been successful (yet) getting single row refreshes to work as expected. Work in progress…

Hi Steve,

What is your choice of backend in this case? If you are using something like Hibernate, where you are getting either proxies or temporary objects from the backend, I’d suggest overriding
DataProvider#getId
to actually match the object by some primary key. By default the Grid uses the objects themselves as their identifiers, but having a stable ID from the backend will reduce the amount of confusion inside the Grid.

Let’s say your typical workflow for a user is to make a change, save it to the backend and see the update in the Grid. Here’s a simplified example of how to do it with Spring Data.

[code]
@Autowired
ItemRepository repo; // Stores Items in a JpaRepository
// Item has an “id” of type Long

DataProvider dataProvider = new CallbackDataProvider(
query → /* Here’s a call to repo to fetch the range I want */,
query → repo.size(), // I don’t support filtering in this example
Item::getId // This tells to map things based on the ID, not the object itself.
);

// In the event handler of user making changes
Item item = getUserEditedItem();
Item updatedItem = repo.save(item); // I get a new reference from save
// Item updatedItem = repo.getOne(item.getId()); // Could also look based on the ID
dataProvider.refreshItem(updatedItem); // Refresh with the new instance
[/code]The example uses the Long id from the Item class as the identity. The most relevant bit is the
Item::getId
extractor for the primary key This goes around the issues of stale elements and proxies. The ID should be always available, not null, and most of all with a stable equals and hashCode implementations. Primitive types are pretty good for such purposes. Hope this gave some ideas on where to go from here. If the example left you questions, I’m more then happy to explain in more details.

//Teemu

Thanks Teemu. First to answer your question, I construct SQL queries programatically for each grid. mySQL, with a home made data access object. The heavy lifting is done in a common base class, so each grid requires only fine tuning. No Hiberate, no JPA.

Your advice works as advertised and has enabled single row refreshes - thanks! But while data refreshes function correctly when the row being updated is not selected, I’m still struggling to apply a change to a selected row, have the change made in the grid and have the selection re-applied. Various attempts have produced proper changes but the selection disappearing, or the selection remaining and the changes sometimes, but not always being shown until something else refreshes the grid.

I think there is a timing problem. I’ll experiment with using a dataProviderListener to trigger a re-selection… Or is it that the MultiSelectionModel, referring to the Items, has that same stale element problem that you solved for data updates?

I was hoping that single row refreshing would help with performance. In fact it has - the grid immediately reflects the change rather than showing the momentary blank/repaint when the whole grid is refreshed. But when there is a selection, I’m getting the same repaint lag. Either I am inadvertantly calling a grid.refreshAll, or the framework is.

hmm… Got same in pure Java… See the code… I’m just so stuck with this.
Also I have a problem that the firstName edit column is added as a new column in the end of the grid… I would need it to be so, that I can just edit the existing columns…

import com.vaadin.data.Binder;
import com.vaadin.data.ValidationException;
import com.vaadin.data.provider.ListDataProvider;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import entity.Person;
import org.vaadin.gridutil.cell.GridCellFilter;



import java.util.Arrays;
import java.util.List;
import java.util.Set;

public class DashboardView extends VerticalLayout implements View {
    //private GridCellFilter filter;

    //private  TestGrid testGrid;
    private GridCellFilter filter;

    private Grid<Person>  grid = new Grid<>(Person.class);

    private List<Person> people = Arrays.asList(
            new Person(1, "kari", "kukkonen", "01111"),
            new Person(2, "matias", "meikalainen", "02222")
    );

    public DashboardView() {
  
        ListDataProvider listDataProvider = new ListDataProvider(people);
        grid.setDataProvider(listDataProvider);

        Binder<Person> binder = grid.getEditor().getBinder();

        Grid.Column<Person, String> column = grid.addColumn(Person::getFirstName).setEditorComponent(new TextField(), Person::setFirstName);
        column.setEditable(true);
        column.setHidden(false);
        column.setCaption("firstName");
        
        grid.setSelectionMode(Grid.SelectionMode.SINGLE);

        // using the GridUtil addon to have the filters.. 
        this.filter = new GridCellFilter(grid, Person.class);
        this.filter.setNumberFilter("id", Integer.class, "You need to use only numbers..", "1", "1000");
        this.filter.setTextFilter("firstName", true,true, "name starts with..");
        this.filter.setTextFilter("lastName", true, true, "lastname starts with..");
        this.filter.setTextFilter("sotu", true, true, "sotu starts with..");

  

        // Localize the editor button captions
        grid.getEditor().setSaveCaption("Tallenna");
        grid.getEditor().setCancelCaption("Peruuta");
        grid.getEditor().setEnabled(true);


        // now just add onclick listeners for save and cancel buttons..
        grid.getEditor().addSaveListener( e -> {

            Set<Person> selectedPeople = e.getGrid().getSelectedItems();
            try {
                binder.writeBean(e.getBean());
                System.out.println("writing the bean.. " + e.getBean().getFirstName() + " : " + e.getBean().getLastName() + " : " + e.getBean().getSotu() + " : " + e.getBean().getId());
                listDataProvider.refreshAll();
                

            } catch (ValidationException e1) {
                e1.printStackTrace();
            }
            for( Person p:  selectedPeople) {
                System.out.println(p.getFirstName() + " : " + p.getLastName());

            }
        });


        grid.setSizeFull();
        grid.setEnabled(true);
        addComponent(grid);
        
    }

    @Override
    public void enter(ViewChangeEvent event) {

        grid.getDataProvider().refreshAll();


    }
}

and I’m getting this kind of error:

java.lang.IllegalStateException: Duplicate key Person(id=1, firstName=kari2, lastName=kukkonen, sotu=01111)
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1245)
at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1540)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.vaadin.data.provider.DataCommunicator$ActiveDataHandler.getActiveData(DataCommunicator.java:165)
at com.vaadin.data.provider.DataCommunicator.refresh(DataCommunicator.java:521)
at com.vaadin.ui.components.grid.SingleSelectionModelImpl.doSetSelected(SingleSelectionModelImpl.java:128)
at com.vaadin.ui.components.grid.SingleSelectionModelImpl.setSelectedFromClient(SingleSelectionModelImpl.java:157)
at com.vaadin.ui.components.grid.SingleSelectionModelImpl$1.deselect(SingleSelectionModelImpl.java:58)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:155)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:116)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:445)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:410)
at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)
at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90)
at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)
at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1568)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:381)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1689)
at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:225)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1174)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1106)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:119)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.eclipse.jetty.server.Server.handle(Server.java:524)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:745)

hmm… I made some debgging and the problem is this:

listDataProvider.refreshAll(); But if I change that to:

listDataProvider.refreshAll(); grid.setDataProvider(listDataProvider); I then get no errors…
But the problem with this, is that If I have a big list, then the grid will slow down, because it will always reassign the data provider…

Hi @Kari Skytta,

Thank you for the tip is worked, but it is a bit ugly having to do that …

This line of code:

private Grid<Person> grid = new Grid<>(Person.class);

Will generate all the columns, including “FirstName”. Then after few lines you are doing this:

column = grid.addColumn( Person::getFirstName).setEditorComponent(new TextField(), Person::setFirstName);

Which will add a
new
column at the end of the previously generated columns. Add specify editor for it.

Instead of
addColumn
you could
getColumn
, but since the current API is a bit liimited you can probably do it a bit differently:

private Grid<Person> grid = new Grid<>();

And then add all the columns manually. You can also use
setCaption
to give it a better header caption.

Now to the first question, I have removed all code related to:

private GridCellFilter filter;

And I’m not getting any errors, suspecting that it might be a problem in GridUtil. Can you reproduce without any external add-ons?

Hi,

I have a very simple example that also created this error and I am not adding any extra columns to the grid, I use one addional textfield to trigger the filter on the grid, send you email and I will post you the example code

Kari, do you have a code for that Person bean as well? It should be really easy after that for developers to look into the issue.

cheers,
matti

The Person is just a normal JAva class with getters and setters for id, firstName, lastName and sotu…

Like this:

public class Person {
private int id;
private String firstName;
private String lastName;
private String sotu;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getSotu() {
return sotu;
}

public void setSotu(String sotu) {
this.sotu = sotu;
}
}

Thanks, I know that I can make it like that. But it’s annoying to do it so that you need to add every column separately… It should just be simple and getColumn should work… So that i could use it like grid.getColumn("sotu).setEditable(true)… But this isn’t working…

The filtering is not and was not a problem…

@Luis:
Is it possible to send a small code snippet here, or report a bug on
Github
?
For private support, you can use:
https://vaadin.com/support

Otherwise, I have a small example adding an additional header to the Grid with some TextFields for filtering, can you reproduce the error in
this code
?

@Kari:
I’m still unable to reproduce :-/ can you proivde a minimal code without add-ons that reproduces the issue?
I’ve also created
an issue
related to the
getColumn
API. I agree, it needs improvments.

Try to override hashCode in the ‘Person’ POJO: don’t use fields what can be changed in vaadin UI to generate hashcode.
It help for me =)

Hi:

I am sorry I found the solution to the problem is was my error I was using a Kotlin data class to render in the grid and trusted the kotlin default implementation of equals and hascode but once I provided my own implementation of it to only consider to items to be the same if they have the same database id I got my problem sorted.

Thank you.
Luis Trigueiros

Kari Skyttä:

AMahdy Abdelaziz:

Kari Skyttä:
Also I have a problem that the firstName edit column is added as a new column in the end of the grid… I would need it to be so, that I can just edit the existing columns…

This line of code:

private Grid<Person> grid = new Grid<>(Person.class);

Will generate all the columns, including “FirstName”. Then after few lines you are doing this:

column = grid.addColumn( Person::getFirstName).setEditorComponent(new TextField(), Person::setFirstName);

Which will add a new column at the end of the previously generated columns. Add specify editor for it.

Instead of addColumn you could getColumn, but since the current API is a bit liimited you can probably do it a bit differently:

private Grid<Person> grid = new Grid<>();

And then add all the columns manually. You can also use setCaption to give it a better header caption.

Now to the first question, I have removed all code related to:

private GridCellFilter filter;

And I’m not getting any errors, suspecting that it might be a problem in GridUtil. Can you reproduce without any external add-ons?

Thanks, I know that I can make it like that. But it’s annoying to do it so that you need to add every column separately… It should just be simple and getColumn should work… So that i could use it like grid.getColumn("sotu).setEditable(true)… But this isn’t working…

The filtering is not and was not a problem…

thanks my lord, works like a champ.