vaadin / flow-components

Java counterpart of Vaadin Web Components
101 stars 66 forks source link

Exception when using ListDataProvider with default grid #1620

Open tulioag opened 5 years ago

tulioag commented 5 years ago

This code generates a ClassCastException Full stacktrace

        Binder<Bean> binder = new Binder<Bean>();
        BinderCrudEditor<Bean> editor = new BinderCrudEditor<>(binder);

        Crud<Bean> crud = new Crud<>(Bean.class, editor);
        add(crud);
        crud.setDataProvider(new ListDataProvider<Bean>(getBeans()));

Creating your own grid and passing it on the constructor bypasses this issue, as described in this post https://vaadin.com/forum/thread/17480248/exception-using-vaadin-crud-with-listdataprovider

Full code

package org.test;

import java.io.Serializable;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.apache.commons.lang3.RandomStringUtils;

import com.vaadin.flow.component.crud.BinderCrudEditor;
import com.vaadin.flow.component.crud.Crud;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.provider.ListDataProvider;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.PWA;

@Route("")
@PWA(name = "My Application", shortName = "My Application")
public class MainView extends VerticalLayout {

    public MainView() {
        Binder<Bean> binder = new Binder<Bean>();
        BinderCrudEditor<Bean> editor = new BinderCrudEditor<>(binder);

        Crud<Bean> crud = new Crud<>(Bean.class, editor);
        add(crud);
        crud.setDataProvider(new ListDataProvider<Bean>(getBeans()));
    }

    private static List<Bean> getBeans() {
        Random random = new Random();
        return IntStream.range(0, 1000).mapToObj(
                i -> new Bean(RandomStringUtils.randomAlphabetic(10), RandomStringUtils.randomAlphabetic(10), random.nextInt(100)))
                .collect(Collectors.toList());
    }

    public static class Bean implements Serializable {

        private String firstName;
        private String lastName;
        private int age;

        public Bean() {}

        public Bean(String firstName, String lastName, int age) {
            super();
            this.firstName = firstName;
            this.lastName = lastName;
            this.age = age;
        }

        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 int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }

    }
}
OlliTietavainenVaadin commented 4 years ago

Stacktrace I get when hitting this issue (to make the exception searchable):

Caused by: java.lang.ClassCastException: class com.vaadin.flow.component.crud.CrudFilter cannot be cast to class com.vaadin.flow.function.SerializablePredicate (com.vaadin.flow.component.crud.CrudFilter and com.vaadin.flow.function.SerializablePredicate are in unnamed module of loader org.eclipse.jetty.webapp.WebAppClassLoader @2534229)
    at java.util.Optional.map (Optional.java:265)
    at com.vaadin.flow.data.provider.ListDataProvider.getFilteredStream (ListDataProvider.java:100)
    at com.vaadin.flow.data.provider.ListDataProvider.size (ListDataProvider.java:87)
    at com.vaadin.flow.data.provider.DataProviderWrapper.size (DataProviderWrapper.java:85)
    at com.vaadin.flow.data.provider.DataCommunicator.getDataProviderSize (DataCommunicator.java:336)
    at com.vaadin.flow.data.provider.DataCommunicator.flush (DataCommunicator.java:453)
    at com.vaadin.flow.data.provider.DataCommunicator.lambda$requestFlush$2f364bb9$1 (DataCommunicator.java:425)
    at com.vaadin.flow.internal.StateTree.lambda$runExecutionsBeforeClientResponse$1 (StateTree.java:368)
    at java.util.ArrayList.forEach (ArrayList.java:1540)
    at com.vaadin.flow.internal.StateTree.runExecutionsBeforeClientResponse (StateTree.java:365)
    at com.vaadin.flow.server.communication.UidlWriter.encodeChanges (UidlWriter.java:411)
    at com.vaadin.flow.server.communication.UidlWriter.createUidl (UidlWriter.java:187)
    at com.vaadin.flow.server.communication.UidlWriter.createUidl (UidlWriter.java:225)
    at com.vaadin.flow.server.BootstrapHandler$BootstrapPageBuilder.getInitialUidl (BootstrapHandler.java:763)
    at com.vaadin.flow.server.BootstrapHandler$BootstrapPageBuilder.setupDocumentHead (BootstrapHandler.java:746)
    at com.vaadin.flow.server.BootstrapHandler$BootstrapPageBuilder.getBootstrapPage (BootstrapHandler.java:524)
    at com.vaadin.flow.server.BootstrapHandler.synchronizedHandleRequest (BootstrapHandler.java:465)
    at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest (SynchronizedRequestHandler.java:40)
    at com.vaadin.flow.server.VaadinService.handleRequest (VaadinService.java:1540)
    at com.vaadin.flow.server.VaadinServlet.service (VaadinServlet.java:247)
    at javax.servlet.http.HttpServlet.service (HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle (ServletHolder.java:876)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter (ServletHandler.java:1623)
    at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter (WebSocketUpgradeFilter.java:214)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter (ServletHandler.java:1610)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle (ServletHandler.java:540)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle (ScopedHandler.java:146)
    at org.eclipse.jetty.security.SecurityHandler.handle (SecurityHandler.java:548)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle (HandlerWrapper.java:132)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle (ScopedHandler.java:257)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle (SessionHandler.java:1711)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle (ScopedHandler.java:255)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle (ContextHandler.java:1347)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope (ScopedHandler.java:203)
    at org.eclipse.jetty.servlet.ServletHandler.doScope (ServletHandler.java:480)
    at org.eclipse.jetty.server.session.SessionHandler.doScope (SessionHandler.java:1678)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope (ScopedHandler.java:201)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope (ContextHandler.java:1249)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle (ScopedHandler.java:144)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle (ContextHandlerCollection.java:220)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle (HandlerCollection.java:152)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle (HandlerWrapper.java:132)
    at org.eclipse.jetty.server.Server.handle (Server.java:505)
    at org.eclipse.jetty.server.HttpChannel.handle (HttpChannel.java:370)
    at org.eclipse.jetty.server.HttpConnection.onFillable (HttpConnection.java:267)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded (AbstractConnection.java:305)
    at org.eclipse.jetty.io.FillInterest.fillable (FillInterest.java:103)
    at org.eclipse.jetty.io.ChannelEndPoint$2.run (ChannelEndPoint.java:117)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask (EatWhatYouKill.java:333)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce (EatWhatYouKill.java:310)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce (EatWhatYouKill.java:168)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce (EatWhatYouKill.java:132)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob (QueuedThreadPool.java:781)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run (QueuedThreadPool.java:917)
    at java.lang.Thread.run (Thread.java:834)
tulioag commented 4 years ago

The main issue is that a CrudGrid is created when using the constructor new Crud<>(Bean.class, editor). CrudGrid requires a DataProvider that understands what a CrudFilter is, but that is not enforced by the compiler since CrudGrid inherits setDataProvider from Grid. ListDataProvider tries to treat CrudFilter as a Predicate, causing the exception. I think some API changes would be needed to fix this issue.