IndexOutOfBoundsException в запросе DataProvider с использованием Java 8 Stream

Я хочу отложить загрузку отфильтрованных данных из серверной части. Если я применяю фильтр, который возвращает 1 элемент (или фильтр не применяется) из бэкэнда, все работает нормально.

Начинает вылетать / бросать OutOfBoundsExceptionесли извлеченных элементов больше 1. Я использовал официальную документацию Vaadin в качестве руководства для моей реализации.

Исключение создается в.filter()метод Stream-API. Мне также известно значение исключения, индекс, который пытается получить доступ к значениям, составляет>= максимальный размер списка, но я не уверен, как это исправить. Установка лимита на limit-1 для первого запроса не исправила.

Я думаю, что делаю что-то не так со вторым запросом в обратном вызове, но не могу понять, в чем проблема. Это проблема Stream-API или второй запрос обратного вызова работает некорректно?

public DataProvider<T, String> createLazyLoadingProvider(List<T> data) {
        DataProvider<T, String> lazyLoadingProvider
                = DataProvider.fromFilteringCallbacks(query -> {
                    // First Query
                    final int offset = query.getOffset();
                    final int limit = query.getLimit();
                    final String filter = query.getFilter().orElse("");

                    return data
                            .stream()
                            .skip(offset)
                            .limit(limit)
                            .filter(e -> {
                                return e.toString().startsWith(filter);
                            });


                }, query -> {
                    // Second query
                    return (int) data.stream()
                            .filter(e -> {
                                return e.toString().startsWith(filter);
                            })
                            .count();
                });
        return lazyLoadingProvider;
    }

Производит:

First Query
Offset: 0
Limit: 100
Callback-Filter: 3
Full Size of Data: 6005
From backend fetched Items: 5
-----------
Second Query
Offset: 0
Limit: 2147483647
Callback-Filter: 3
Max fetchable Items with filter applied: 381

Трассировки стека:

java.lang.IndexOutOfBoundsException: индекс 5 выходит за пределы для длины 5 в java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64) в java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70) в java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248) в java.base/java.util.Objects.checkIndex(Objects.java:372) в java.base/java.util.ArrayList.get(ArrayList.java:458) в com.vaadin.flow.data.provider.DataCommunicator.lambda$getJsonItems$3(DataCommunicator.java:611) в java.base/java.util.stream.IntPipeline$1$1.accept(IntPipeline.java:180) в java.base/java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:104) в java.base/java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:699) на java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) в java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) в java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) в java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) в java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) на com.vaadin.flow.data.provider.DataCommunicator.getJsonItems(DataCommunicator.java:613) на com.vaadin.flow.data.provider.DataCommunicator.collectChangesToSend(DataCommunicator.java:556) на com.vaadin.flow.data.provider.DataCommunicator.flush(DataCommunicator.java:473) на com.vaadin.flow.data.provider.DataCommunicator.lambda$requestFlush$2f364bb9$1(DataCommunicator.java:421) на com.vaadin.flow.internal.StateTree.lambda$runExecutionsBeforeClientResponse$1(StateTree.java:364) в java.base/java.util.ArrayList.forEach(ArrayList.java:1540) в com.vaadin.flow.internalRBecponseTreecreecount. (StateTree.java:361) на com.vaadin.flow.server.communication.UidlWriter.encodeChanges(UidlWriter.java:392) на com.vaadin.flow.server.communication.UidlWriter.createUidl(UidlWriter.java:182) в com.vaadin.flow.server.communication.UidlRequestHandler.writeUidl(UidlRequestHandler.java:116) в com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:116) SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) в com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1540) в com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:246) в javax.servlet.http.HttpServlet.service(HttpServlet.java:750) в org.eclipse.jetty.servlet.Servlet.Servlet. (ServletHolder.java:760) по адресу org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1617) по адресу org.eclipse.jetty.websocket.server.WebSocketUpgradeFilterFilterSocket.server.WebSocketUpgradeFilter: org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604) в org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:545) в org.eclipser.handler.jet.ScopedHandler.handle(ScopedHandler.java:143) в org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:536) в org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) в org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235) в org.eclipse.jetty.server.session.SessionHandler.doHandle(ScopedHandler.java:1592) в org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) в org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1296) в org.eclipse.jetty.ser.handler.ScopedHandler.nextScope(ScopedHandler.java:188) в org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:485) в org.eclipse.jetty.server.session.SessionHandler.doSession (Sava:1562) на org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) на org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1211) в org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) в org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:221) в org.eclipse.jetty.server.handle.HandlerCollection.handle(HandlerCollection.java:146) в org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:717) в org.eclipse.jetty.server.handler.HandlerCollection.handle. (HandlerCollection.handle. java:146) на org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) на org.eclipse.jetty.server.Server.handle(Server.java:500) на org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:386) на org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:562) на org.eclipse.jetty.server.HttpChannel (.java:378) в орг.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:270) по адресу org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) по адресу org.eclipse.jetty.io.FillInterestFillInterest.java:103) в org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:543) в org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection).java на org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:161) на org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) на org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117) по адресу org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336) по адресу org.eclipse.jetty.util.thread.hatProductYou.Eat. (EatWhatYouKill.java:313) по адресу org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171) по адресу org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYou12).eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:388) по адресу org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806) по адресу org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)..thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938) в java.base/java.lang.Thread.run(Thread.java:834)388) в org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806) в org.eclipse.jetty.util.thread.QueuedThreadPool $ Runner.run (в QueuedThreadPool.java:938) /java.lang.Thread.run(Thread.java:834)388) в org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806) в org.eclipse.jetty.util.thread.QueuedThreadPool $ Runner.run (в QueuedThreadPool.java:938) /java.lang.Thread.run(Thread.java:834)

1 ответ

Решение

Перед применением смещения и ограничения необходимо выполнить фильтрацию.

Доработка:

Скажите, что у вас есть предметы Apple, Cucumber, Lemon, Lettuce, Linseed, Lime, Tangerine, Tomato и хотите, чтобы фильтр включал только те, которые начинаются с L.

Ваш подсчетный запрос возвращает количество 4 (Lemon, Lettuce, Linseed, Lime).

Теперь предположим, что сетке нужны первые два элемента, поэтому она отправляет смещение 0 и ограничение 2.

Ваш код выбирает первые два элемента, Apple, Cucumber, затем фильтрует их и возвращает 0 элементов.

Что ему нужно сделать, так это отфильтровать элементы, чтобы получить Lemon, Lettuce, Linseed, Lime, затем возьмите смещение 0 и ограничение 2, чтобы получить Lemon, Lettuce.

Другие вопросы по тегам