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
>

Reply via email to