LazyDataModel java.lang.IndexOutOfBoundsException: toIndex =

UI Components for JSF
Post Reply
smithh032772
Posts: 6144
Joined: 10 Sep 2011, 21:10

19 Dec 2011, 16:01

Code: Select all

SEVERE: java.lang.IndexOutOfBoundsException: toIndex = 1126
I am using LazyDataModel with custom filter options/buttons/UI-controls; these filter options always filter the datasource via SQL SELECT. When filtering the datasource via SQL SELECT (see code below), I am experiencing the above error when dataTable is rendered.

Code: Select all

lazyDataModel = new Lazy{EntityName}DataModel( getFacade().filterBy(filterBy fields, ...));
it seems to occur when page # (BEFORE filter) > new page # (AFTER filter). I mentioned this behavior in another topic (URL below), but I am no longer using JumpToPageDropDown, since Cagatay stated that it is not supported. I believe this issue is related to LazyDataModel.

viewtopic.php?f=3&t=16466&p=51215#p51215

I don't see/experience this behavior all the time, it is sporadic. I can't even find the PrimeFaces code that references toIndex. I think it is related to rendering lazyDataModel after load or paging.
Howard

PrimeFaces 6.0, Extensions 6.0.0, Push (Atmosphere 2.4.0)
TomEE+ 1.7.4 (Tomcat 7.0.68), MyFaces Core 2.2.9, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

Java EE 6 Tutorial|NetBeans|Google|Stackoverflow|PrimeFaces|Apache

smithh032772
Posts: 6144
Joined: 10 Sep 2011, 21:10

20 Dec 2011, 05:47

Okay, this error is caused by LazyDataModel sample code, which calls the subList method of the Interface List<E>.

The following code is at the end of LazyDataModel sample code:

Code: Select all

        //paginate
        if(dataSize > pageSize) {
            try {
                return data.subList(first, first + pageSize);
            }
            catch(IndexOutOfBoundsException e) {
                return data.subList(first, first + (dataSize % pageSize));
            }
        }
        else {
            return data;
        }
subList accepts, returns, and throws the following:

Parameters:
fromIndex - low endpoint (inclusive) of the subList
toIndex - high endpoint (exclusive) of the subList

Returns:
a view of the specified range within this list

Throws:
IndexOutOfBoundsException - for an illegal endpoint index value (fromIndex < 0 || toIndex > size || fromIndex > toIndex)

I will try to work on or research a solution.
Howard

PrimeFaces 6.0, Extensions 6.0.0, Push (Atmosphere 2.4.0)
TomEE+ 1.7.4 (Tomcat 7.0.68), MyFaces Core 2.2.9, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

Java EE 6 Tutorial|NetBeans|Google|Stackoverflow|PrimeFaces|Apache

smithh032772
Posts: 6144
Joined: 10 Sep 2011, 21:10

20 Dec 2011, 07:42

I modified the code as follows:

Code: Select all

        /*
         * IndexOutOfBoundsException thrown under the following conditions:
         * 
         * fromIndex < 0 || toIndex > size || fromIndex > toIndex
         * 
         * http://docs.oracle.com/javase/6/docs/api/java/util/List.html#subList%28int%2C%20int%29
         */
        if (first < 0 || first > dataSize) {
            System.out.println(this.getClass().toString() + ".load(): paginate: first < 0 || first > dataSize; dataSize=" + dataSize + "; first=" + first);
        }

        if(dataSize > pageSize && first >= 0) {
            System.out.println(this.getClass().toString() + ".load(): paginate: dataSize > pageSize; dataSize=" + dataSize + "; pageSize=" + pageSize + "; first=" + first);
            try {
                /*
                 * first > dataSize can occur when previous dataSize > current dataSize
                 * return the last page of the current dataSize
                 */
                if (first > dataSize) {
                    Integer lastPageSize = (dataSize % pageSize);
                    first = dataSize - lastPageSize;
                    pageSize = lastPageSize;
                    System.out.println(this.getClass().toString() + ".load(): paginate: first > dataSize; RECALCULATED first=" + first + "; pageSize=" + pageSize);
                }
                if (first < 0) 
                    return data;
                else
                    return data.subList(first, first + pageSize);
            }
            catch(IndexOutOfBoundsException e) {
                // this always occur when click on last page button on p:dataTable paginator
                System.out.println(this.getClass().toString() + ".load(): paginate: caught IndexOutOfBoundsException e.getLocalizedMessage()=" + e.getLocalizedMessage() + "; e.getMessage()=" + e.getMessage());
                return data.subList(first, first + (dataSize % pageSize));
            }
        }
        else {
            System.out.println(this.getClass().toString() + ".load(): paginate: dataSize <= pageSize && first < 0; dataSize=" + dataSize + "; pageSize=" + pageSize);
            return data;
        }
    }
EDIT: (listed below)
1. code above works better with (PrimeFaces) p:dataTable UIComponent (no need to update paginator controls on xhtml/jsf page)
2. have not tested with JSF standard h:dataTable since I prefer to use p:dataTable and using p:dataTable (LazyDataModel) throughout JSF/PrimeFaces app
3. I recommend code above, and you can remove the System.out.println() statements, of course
Howard

PrimeFaces 6.0, Extensions 6.0.0, Push (Atmosphere 2.4.0)
TomEE+ 1.7.4 (Tomcat 7.0.68), MyFaces Core 2.2.9, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

Java EE 6 Tutorial|NetBeans|Google|Stackoverflow|PrimeFaces|Apache

andrew_wot
Posts: 1
Joined: 05 Jan 2012, 02:55

05 Jan 2012, 03:06

Well, this code doesn't work if dataSize falls on page boundary (e.g. page size 10 and dataSize 10).
The modified version

Code: Select all

            int dataSize = docIds.size();
            if (first >= dataSize) {
                first = ((dataSize - 1) / pageSize) * pageSize;
            } 
            return docIds.subList(first, Math.min(first + pageSize, dataSize))))
You would also need this to fix dreaded "/ by 0" in setRowIndex

Code: Select all

      /**
         * Fix for Primefaces bug division by 0.
         * http://code.google.com/p/primefaces/issues/detail?id=1544
         */
        @Override
        public void setRowIndex(int rowIndex) {
            if (getPageSize() == 0) {
                super.setRowIndex(-1);
            } else {
                super.setRowIndex(rowIndex);
            }    
        }

smithh032772
Posts: 6144
Joined: 10 Sep 2011, 21:10

05 Jan 2012, 03:28

Thanks for the response, and fixed the dreaded "/ by 0" in setRowIndex, earlier.
Howard

PrimeFaces 6.0, Extensions 6.0.0, Push (Atmosphere 2.4.0)
TomEE+ 1.7.4 (Tomcat 7.0.68), MyFaces Core 2.2.9, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

Java EE 6 Tutorial|NetBeans|Google|Stackoverflow|PrimeFaces|Apache

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 48 guests