Hi Martin, My bad, as always I should have made a small unit test before concluding something.
My detach-cascade assumption was incorrect, with regard to ListView. Wicket’s ListItemModel does not, in fact, do a detach cascade. So while it *is* getting detached mid-render, that does not lead to any issues with the ListView model… Oh well, back to the drawing board to figure out what is happening here in our app; These “once every 6 months” bugs are something else. The observed behavior when the bug occurs *should not be possible* stepping through the code. But of course those are the bugs that are most satisfying to fix 🙂 Met vriendelijke groet, Kind regards, Bas Gooren Op 27 feb 2026, 09:18:52 schreef Martin Terra via users < [email protected]>: > Can you post a quickstart that reproduces the issue? > > to 26.2.2026 klo 17.43 Bas Gooren via users ([email protected]) > kirjoitti: > > Hi all, > > > I have an interesting case, which I will admit I lost some sleep over 😉 > > > The ListView API is not stable WRT its model. > > > We have not been able to reproduce this, but this is what we get in > > production: > > > Caused by: java.lang.NullPointerException: Cannot invoke > > "java.util.List.get(int)" because the return value of > > "org.apache.wicket.markup.html.list.ListView.getModelObject()" is null > > at > > > > org.apache.wicket.markup.html.list.ListItemModel.getObject(ListItemModel.java:55) > > ~[wicket-core-9.19.0.jar:9.19.0] > > at ....SectionsPanel.createSection(SectionsPanel.java:57) ~[-] > > at ....SectionsPanel$1.populateItem(SectionsPanel.java:48) ~[-] > > at > > org.apache.wicket.markup.html.list.ListView.onPopulate(ListView.java:523) > > ~[wicket-core-9.19.0.jar:9.19.0] > > at > > > > org.apache.wicket.markup.repeater.AbstractRepeater.onBeforeRender(AbstractRepeater.java:124) > > ~[wicket-core-9.19.0.jar:9.19.0] > > at org.apache.wicket.Component.beforeRender(Component.java:949) > > ~[wicket-core-9.19.0.jar:9.19.0] > > at > > > > org.apache.wicket.MarkupContainer.onBeforeRenderChildren(MarkupContainer.java:1759) > > ~[wicket-core-9.19.0.jar:9.19.0] > > > The simplest way to explain this: > > > We have a ListView in a stateless page. > > The ListView gets a list model mapped from an LDM on the page: > > > var parentModel = LoadableDetachableModel.of(() -> > > fetchItemFromCacheAndExternalApi()); > > … = new ListView(“id”, parentModel.map(Parent::getItems)) { … } > > > For a reason unknown at this time, which only happens under high load, this > > stateless page is re-rendered. > > > On the re-render of the ListView, it walks through its onPopulate method. > > > First it calls getViewSize() to check if there are items to render (parent > > model is non-null and says: here’s a list of X items) > > Reuse items is off, so it calls removeAll => all children are removed and > > detached => which also detaches the list model and the page model > > It then assumes the “size” is still correct and starts creating and > > appending children (ListItem instances). > > Once those populate and call their ListItemModel.getObject(), the parent > > model reattaches and now returns null => Boom, there’s the NPE. > > > The reason that our page model returns non-null and null in quick > > succession is spam bots and thus cache issues; An external API we load data > > from also seems to misbehave and sometimes return empty results under load. > > This particular issue caught me by suprise, as normally a LDM is only > > loaded once during render cycle; Here it loads *twice*: for getViewSize() > > and then for the first ListItemModel, because it got detached by > > ListView#removeAll. > > > But more to the point: the ListView proceeds, after calling removeAll(), as > > if nothing can have changed. And that is not correct, the ListView model > > may have been detached by removing children and thus have a different value > > now. > > > Should ListView not re-calculate/query getViewSize() after calling > > removeAll()? That would remove this edge case? > > > Met vriendelijke groet, > > Kind regards, > > > Bas Gooren > > >
