-
Bug
-
Resolution: Fixed
-
Major
-
8.6.0, 9.0.1
-
None
-
Security Level: Jimmy
-
None
-
ZK 9.5.0 S1
Steps to Reproduce
Run fiddle
https://zkfiddle.org/sample/h0diii/3-Grid-ROD-IndexOutOfBounds-example#source-2
Current Result
In Java console:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at java.util.ArrayList.rangeCheck(Unknown Source) at java.util.ArrayList.get(Unknown Source) at org.zkoss.zul.ListModelList.getElementAt(ListModelList.java:158) at org.zkoss.zul.Grid$Renderer.render(Grid.java:1246) at org.zkoss.zul.Grid.doInitRenderer(Grid.java:1126) at org.zkoss.zul.Grid.onInitRender(Grid.java:1081) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:3165) at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:3096) at org.zkoss.zk.ui.impl.EventProcessor.process(EventProcessor.java:138) at org.zkoss.zk.ui.impl.UiEngineImpl.processEvent(UiEngineImpl.java:1890) at org.zkoss.zk.ui.impl.UiEngineImpl.process(UiEngineImpl.java:1662) at org.zkoss.zk.ui.impl.UiEngineImpl.execNewPage0(UiEngineImpl.java:556) at org.zkoss.zk.ui.impl.UiEngineImpl.execNewPage(UiEngineImpl.java:377) at org.zkoss.zk.ui.http.DHtmlLayoutServlet.process(DHtmlLayoutServlet.java:215) at org.zkoss.zk.ui.http.DHtmlLayoutServlet.doGet(DHtmlLayoutServlet.java:140) at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:401) at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at org.mortbay.jetty.Server.handle(Server.java:326) at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:928) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549) at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212) at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
in Client, error window:
Index: 0, Size: 0
Expected Result
No error
Debug Information
When the listmodel has been linked to a grid with grid.setModel(model)
Calling model.add(entry) cause the grid to generate Row objects for each entry (during afterCompose)
Creating row at:
Row.<init>() line: 39 Row.<init>() line: 39 LiveGridDataLoader(GridDataLoader).newRow(RowRenderer) line: 203 LiveGridDataLoader(GridDataLoader).newUnloadedItem(Object, int) line: 189 LiveGridDataLoader.loadModel(int, int) line: 230 LiveGridDataLoader.syncModel(int, int) line: 187 LiveGridDataLoader.doLiveListDataChange(ListDataEvent) line: 114 LiveGridDataLoader.doListDataChange(ListDataEvent) line: 96 Grid.onListDataChange(ListDataEvent) line: 1175 Grid.access$1500(Grid, ListDataEvent) line: 220 Grid$2.onChange(ListDataEvent) line: 916 ListModelList<E>(AbstractListModel<E>).fireEvent(int, int, int) line: 73 ListModelList<E>.add(E) line: 170 GridOutOfBoundsComposer.doAfterCompose(Component) line: 23 UiEngineImpl.doAfterCompose(Composer, Component) line: 625
If later during afterCompose, the model is updated (with clear() for example), the grid still has these row objects preloaded during onInitRender(), resulting is the grid trying to poll model data for rows that no longer have a model entry matching their index in the ListModel
Grid.doInitRenderer() line: 1125 Grid.doInitRenderer() line: 1125 Grid.onInitRender() line: 1081 NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: not available DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available Method.invoke(Object, Object...) line: not available Grid(AbstractComponent).service(Event, Scope, List<EventListenerInfo>, EventHandler, Method, boolean) line: 3165 Grid(AbstractComponent).service(Event, Scope) line: 3096 EventProcessor.process() line: 138 UiEngineImpl.processEvent(Desktop, Component, Event) line: 1890
Workaround
Force the grid to reset ListModel information by setting a null model, then setting the right model:
grid.setModel((ListModel)null);
grid.setModel(myModel);