Grid order of a nested property lead to infinite loop

Hello everyone

During our migration from Vaadin 7 to Vaadin 8, we extended the Vaadin 8 Grid in order to make it behave like a V7 Table, and until now, nothing really problematic happened.

But last week our tester found that trying to order the grid’s data by clicking on the header fails badly, causing an infinite loop and blocking the UI indefinitely.

This behavior didn’t occur on many columns, only on some which contains nested entity data, but not on all of those.

The Grid is working with a custom DataProvider, the JpaDataProvider which get data from our DB through JPA, as it’s name implies.

The Provider is already out of cause, it is implicated in the loop, but just by obeying the fetch and size calls from the DataCommunicator.

After adding logs to Grid and DataCommunicator (especially where the boolean reset is set to true), it seems that the loop is caused by the setDataProvider(DataProvider<T, F> dataProvider, F initialFilter) in the DataCommunicator, itself called by internalSetDataProvider(DataProvider<T, F> dataProvider) from AbstractListing.

I don’t understand why these are called in the process of reordering the Grid, but the logs don’t lie, this method seems to be the culprit for setting reset to true.

I’ve debugged the whole thing during at least 8 hours without any more leads.

Here is the log for the first iterations of the loop after clicking on a header :

15:42:31,790 INFO  [com.vaadin.ui.Grid]
 Sort directions : [com.vaadin.data.provider.GridSortOrder@5531ed82]

15:42:31,791 INFO  [com.vaadin.ui.Grid]
 Sorting... 
15:42:31,791 INFO  [com.vaadin.ui.Grid]
 Columns    : [44]

15:42:31,791 INFO  [com.vaadin.ui.Grid]
 Directions : [ASCENDING]

15:42:31,800 INFO  [com.vaadin.ui.Grid]
 Set Backend sorting
15:42:31,800 INFO  [com.vaadin.data.provider.DataCommunicator]
 Resetting
15:42:31,800 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getClass : class com.vaadin.data.provider.Query
15:42:31,800 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getFilter : Optional.empty
15:42:31,800 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getLimit : 2147483647
15:42:31,800 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getOffset : 0
15:42:31,800 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 getQuery(class java.lang.Long, com.vaadin.data.provider.Query@2d242dc0 )
15:42:31,800 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 Query Orders []
15:42:31,800 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 orderProperties [id - DESCENDING]

15:42:31,800 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 sort -> 1 - [org.eclipse.persistence.internal.jpa.querydef.PathImpl@5dc60186]

15:42:31,800 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 Retrieving count from CriteriaQuery
15:42:31,803 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 [class our.project.entities.Task]
 size -> 11546
15:42:31,803 INFO  [com.vaadin.data.provider.DataCommunicator]
 beforeClientResponse (false)
15:42:31,803 INFO  [com.vaadin.data.provider.DataCommunicator]
 sendDataToClient(false) - reset ? false
15:42:31,879 INFO  [com.vaadin.data.provider.DataCommunicator]
 beforeClientResponse (false)
15:42:31,880 INFO  [com.vaadin.data.provider.DataCommunicator]
 sendDataToClient(false) - reset ? false
15:42:31,880 INFO  [com.vaadin.data.provider.DataCommunicator]
 Sending data to client : 0 -> 100
15:42:31,880 INFO  [com.vaadin.data.provider.DataCommunicator]
 Fetch items 0 -> 100 - Backend sorting [com.vaadin.data.provider.QuerySortOrder@7d3fb6b7]
 - inMemSort com.vaadin.ui.Grid$$Lambda$357/1843311096@6f758522
15:42:31,880 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getClass : class our.project.entities.Task
15:42:31,880 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getFilter : Optional.empty
15:42:31,880 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getLimit : 100
15:42:31,880 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getOffset : 0
15:42:31,880 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getSortOrders : {partnerContact.lastname=ASCENDING}
15:42:31,880 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getInMemorySorting : com.vaadin.ui.Grid$$Lambda$357/1843311096@6f758522
15:42:31,880 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 getQuery(class our.project.entities.Task, com.vaadin.data.provider.Query@54ee0703 )
15:42:31,880 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 Query Orders [partnerContact.lastname - ASCENDING]

15:42:31,881 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 orderProperties [id - DESCENDING]

15:42:31,881 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 sort -> 2 - [org.eclipse.persistence.internal.jpa.querydef.PathImpl@11159cd9, org.eclipse.persistence.internal.jpa.querydef.PathImpl@35e747e7]

15:42:31,884 INFO  [com.vaadin.data.provider.DataCommunicator]
 ======<<<<====== Reset positionned in setDataProvider ! 
15:42:31,916 INFO  [com.vaadin.data.provider.DataCommunicator]
 beforeClientResponse (false)
15:42:31,917 INFO  [com.vaadin.data.provider.DataCommunicator]
 sendDataToClient(false) - reset ? true
15:42:31,917 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getClass : class com.vaadin.data.provider.Query
15:42:31,917 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getFilter : Optional.empty
15:42:31,917 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getLimit : 2147483647
15:42:31,917 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getOffset : 0
15:42:31,917 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 getQuery(class java.lang.Long, com.vaadin.data.provider.Query@67f65a87 )
15:42:31,917 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 Query Orders []
15:42:31,917 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 orderProperties [id - DESCENDING]

15:42:31,918 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 sort -> 1 - [org.eclipse.persistence.internal.jpa.querydef.PathImpl@39497ff4]

15:42:31,918 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 Retrieving count from CriteriaQuery
15:42:31,920 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 [class our.project.entities.Task]
 size -> 11546
15:42:31,920 INFO  [com.vaadin.data.provider.DataCommunicator]
 Sending data to client : 0 -> 100
15:42:31,920 INFO  [com.vaadin.data.provider.DataCommunicator]
 Fetch items 0 -> 100 - Backend sorting [com.vaadin.data.provider.QuerySortOrder@7d3fb6b7]
 - inMemSort com.vaadin.ui.Grid$$Lambda$357/1843311096@6f758522
15:42:31,920 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getClass : class our.project.entities.Task
15:42:31,920 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getFilter : Optional.empty
15:42:31,920 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getLimit : 100
15:42:31,920 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getOffset : 0
15:42:31,921 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getSortOrders : {partnerContact.lastname=ASCENDING}
15:42:31,921 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getInMemorySorting : com.vaadin.ui.Grid$$Lambda$357/1843311096@6f758522
15:42:31,921 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 getQuery(class our.project.entities.Task, com.vaadin.data.provider.Query@5deb7fb2 )
15:42:31,921 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 Query Orders [partnerContact.lastname - ASCENDING]

15:42:31,921 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 orderProperties [id - DESCENDING]

15:42:31,921 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 sort -> 2 - [org.eclipse.persistence.internal.jpa.querydef.PathImpl@24731866, org.eclipse.persistence.internal.jpa.querydef.PathImpl@2263f5b5]

15:42:31,964 INFO  [com.vaadin.data.provider.DataCommunicator]
 beforeClientResponse (false)
15:42:31,964 INFO  [com.vaadin.data.provider.DataCommunicator]
 sendDataToClient(false) - reset ? false
15:42:31,964 INFO  [com.vaadin.data.provider.DataCommunicator]
 Sending data to client : 0 -> 100
15:42:31,964 INFO  [com.vaadin.data.provider.DataCommunicator]
 Fetch items 0 -> 100 - Backend sorting [com.vaadin.data.provider.QuerySortOrder@7d3fb6b7]
 - inMemSort com.vaadin.ui.Grid$$Lambda$357/1843311096@6f758522
15:42:31,964 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getClass : class our.project.entities.Task
15:42:31,964 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getFilter : Optional.empty
15:42:31,964 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getLimit : 100
15:42:31,964 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getOffset : 0
15:42:31,965 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getSortOrders : {partnerContact.lastname=ASCENDING}
15:42:31,965 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getInMemorySorting : com.vaadin.ui.Grid$$Lambda$357/1843311096@6f758522
15:42:31,965 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 getQuery(class our.project.entities.Task, com.vaadin.data.provider.Query@3a2f2868 )
15:42:31,965 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 Query Orders [partnerContact.lastname - ASCENDING]

15:42:31,965 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 orderProperties [id - DESCENDING]

15:42:31,965 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 sort -> 2 - [org.eclipse.persistence.internal.jpa.querydef.PathImpl@2ddb0423, org.eclipse.persistence.internal.jpa.querydef.PathImpl@6e741598]

15:42:31,967 INFO  [com.vaadin.data.provider.DataCommunicator]
 ======<<<<====== Reset positionned in setDataProvider ! 
15:42:31,990 INFO  [com.vaadin.data.provider.DataCommunicator]
 beforeClientResponse (false)
15:42:31,990 INFO  [com.vaadin.data.provider.DataCommunicator]
 sendDataToClient(false) - reset ? true
15:42:31,990 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getClass : class com.vaadin.data.provider.Query
15:42:31,990 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getFilter : Optional.empty
15:42:31,990 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getLimit : 2147483647
15:42:31,990 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getOffset : 0
15:42:31,990 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 getQuery(class java.lang.Long, com.vaadin.data.provider.Query@6b8fbe39 )
15:42:31,992 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 Query Orders []
15:42:31,992 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 orderProperties [id - DESCENDING]

15:42:31,992 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 sort -> 1 - [org.eclipse.persistence.internal.jpa.querydef.PathImpl@3ab0fbff]

15:42:31,992 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 Retrieving count from CriteriaQuery
15:42:31,994 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 [class our.project.entities.Task]
 size -> 11546
15:42:31,994 INFO  [com.vaadin.data.provider.DataCommunicator]
 Sending data to client : 0 -> 100
15:42:31,994 INFO  [com.vaadin.data.provider.DataCommunicator]
 Fetch items 0 -> 100 - Backend sorting [com.vaadin.data.provider.QuerySortOrder@7d3fb6b7]
 - inMemSort com.vaadin.ui.Grid$$Lambda$357/1843311096@6f758522
15:42:31,994 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getClass : class our.project.entities.Task
15:42:31,994 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getFilter : Optional.empty
15:42:31,994 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getLimit : 100
15:42:31,994 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getOffset : 0
15:42:31,994 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getSortOrders : {partnerContact.lastname=ASCENDING}
15:42:31,994 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getInMemorySorting : com.vaadin.ui.Grid$$Lambda$357/1843311096@6f758522
15:42:31,994 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 getQuery(class our.project.entities.Task, com.vaadin.data.provider.Query@4b435b7a )
15:42:31,995 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 Query Orders [partnerContact.lastname - ASCENDING]

15:42:31,995 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 orderProperties [id - DESCENDING]

15:42:31,995 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 sort -> 2 - [org.eclipse.persistence.internal.jpa.querydef.PathImpl@78619eaf, org.eclipse.persistence.internal.jpa.querydef.PathImpl@29a88252]

15:42:32,021 INFO  [com.vaadin.data.provider.DataCommunicator]
 beforeClientResponse (false)
15:42:32,021 INFO  [com.vaadin.data.provider.DataCommunicator]
 sendDataToClient(false) - reset ? false
15:42:32,021 INFO  [com.vaadin.data.provider.DataCommunicator]
 Sending data to client : 0 -> 100
15:42:32,021 INFO  [com.vaadin.data.provider.DataCommunicator]
 Fetch items 0 -> 100 - Backend sorting [com.vaadin.data.provider.QuerySortOrder@7d3fb6b7]
 - inMemSort com.vaadin.ui.Grid$$Lambda$357/1843311096@6f758522
15:42:32,021 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getClass : class our.project.entities.Task
15:42:32,021 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getFilter : Optional.empty
15:42:32,021 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getLimit : 100
15:42:32,021 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getOffset : 0
15:42:32,021 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getSortOrders : {partnerContact.lastname=ASCENDING}
15:42:32,021 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 fetch... getInMemorySorting : com.vaadin.ui.Grid$$Lambda$357/1843311096@6f758522
15:42:32,021 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 getQuery(class our.project.entities.Task, com.vaadin.data.provider.Query@2188fd5c )
15:42:32,022 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 Query Orders [partnerContact.lastname - ASCENDING]

15:42:32,022 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 orderProperties [id - DESCENDING]

15:42:32,022 DEBUG [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 sort -> 2 - [org.eclipse.persistence.internal.jpa.querydef.PathImpl@33b8bd20, org.eclipse.persistence.internal.jpa.querydef.PathImpl@55bcd416]

15:42:32,026 INFO  [com.vaadin.data.provider.DataCommunicator]
 ======<<<<====== Reset positionned in setDataProvider ! 
15:42:32,112 INFO  [com.vaadin.data.provider.DataCommunicator]
 beforeClientResponse (false)
15:42:32,113 INFO  [com.vaadin.data.provider.DataCommunicator]
 sendDataToClient(false) - reset ? true
15:42:32,113 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getClass : class com.vaadin.data.provider.Query
15:42:32,113 WARN  [org.vaadin.addon.jpaadvcontainer.JpaDataProvider]
 size... getFilter : Optional.empty

After a new analysis, I’ve discovered that the cause was not within Vaadin. The problem was in my use of Criteria API with EclipseLink. Ordering a column of a nested entity was causing an inner join in the generated request instead of a left join, so no results were returned, or much less than what the grid expected, which caused a loop of data fetching Vaadin side.
With a better resolution of the path of my properties within the provider, all works fine.