It's hard to give specifics as the form is very complex. I do have a general
example of a pattern prevalent throughout the form. The pseudo code goes
something like this:
// Page
class MyPage extends Page {
onInitialize() {
Panel p = PanelFactory.createPanel("myPanel", "myObject");
this.add(p);
}
}
// Factory for creating panels that use a document cache based loadable
detachable
// model
class PanelFactory {
Panel createPanel(String panelName, String cachedObjectName) {
// uses the document name to retrieve doc from the cache using it's
name
DocumentCacheLDM ldm = new DocumentCacheLDM(cachedObjectName);
// return a panel initialized with the model
if ("myPanel".equals(panelName)) {
return new MyPanel(ldm);
}
....
}
}
// Panel
class MyPanel extends Panel {
MyPanel(final IModel cacheLDM) {
// create an LDM that uses the cache LDM and an expression. Note
that it is marked final
// so it can be used in the list panel below
final LoadableDetachableModel abc = new
LoadableDetachableExpressionModel(cacheLDM, "a.b.c");
// another one based on abc
LoadableDetachableModel def = new
LoadableDetachableExpressionModel(abc, "d.e.f");
// create a panel for DEF object
Panel subPanel = new SubPanel(def);
this.add(subPanel);
// create a model for a repeating list of GHI
LoadableDetachableModel ghi = new
LoadableDetachableExpressionModel(abc, "g.h.i");
// create a repeating section for GHIs
ListPanel<GHI> listPanel = new ListPanel<GHI>("listPanel", ghi) {
@Override
public Component createItemComponent(String id, IModel<GHI>
model, Item item) {
return new GHIPanel(id, model, isReadonly, mode);
}
@Override
public void addItem(AjaxRequestTarget target) {
// uses abc model from above to add the new GHI
abc.getObject().addNewGHI();
}
@Override
public IModel<GHI> getItemModel(GHI item) {
// create an LDM for the GHI item that might use the items's
id internally
// to load
return new LoadableDetachableExpressionModel(abc, item);
}
@Override
public void removeItem(GHI item, AjaxRequestTarget target) {
abc.getObject().deleteGHI(item);
}
}
this.add(listPanel);
}
}
This pattern, in our case, seems to end with a bunch of models that never
get detached. Therefore on subsequent request we end up with some parts of
the form reattached to the document from the cache and other parts attached
to orphaned transient models from their unattached models. Then when you
submit the form the components that are attached to the cached object update
the correct model object but the ones that didn't get detached properly
update the orphaned model objects. So we end up with data lose. To get
this working we changed the MyPanel class to something like this:
// Panel
class MyPanel extends Panel {
private LoadableDetachableModel abc;
private LoadableDetachableModel def;
private LoadableDetachableModel ghi;
void onDetach() {
abc.detach();
def.detach();
ghi.detach();
}
MyPanel(final IModel cacheLDM) {
// create an LDM that uses the cache LDM and an expression
abc = new LoadableDetachableExpressionModel(cacheLDM, "a.b.c");
// another one based on abc
def = new LoadableDetachableExpressionModel(abc, "d.e.f");
// create a panel for DEF object
Panel subPanel = new SubPanel(def);
this.add(subPanel);
// create a model for a repeating list of GHI
ghi = new LoadableDetachableExpressionModel(abc, "g.h.i");
// create a repeating section for GHIs
ListPanel<GHI> listPanel = new ListPanel<GHI>("listPanel", ghi) {
@Override
public Component createItemComponent(String id, IModel<GHI>
model, Item item) {
return new GHIPanel(id, model, isReadonly, mode);
}
@Override
public void addItem(AjaxRequestTarget target) {
// uses abc model from above to add the new GHI
abc.getObject().addNewGHI();
}
@Override
public IModel<GHI> getItemModel(GHI item) {
// create an LDM for the GHI item that might use the items's
id internally
// to load
return new LoadableDetachableExpressionModel(abc, item);
}
@Override
public void removeItem(GHI item, AjaxRequestTarget target) {
abc.getObject().deleteGHI(item);
}
}
this.add(listPanel);
}
}
After instrumenting LoadableDetachableModel and RequestCycle to track all
the LDMs, we can now see that after the detach process executes at the end
of the request cycle all of the models are detached and the problems appear
to go away.
Does this solution make sense? Is there something fundamentally wrong with
the pattern? Is it because we don't set a model on MyPanel thereby breaking
the detach process somehow? Is the use of the final "abc" model in the list
panel anonymous inner type causing inadvertent serialization problems?
We are using Wicket 6 and the problem doesn't become prevalent until the
form has been mildly stressed. Presumably this is because we have reached
some threshold that starts to trigger some Wicket serialization behaviour.
Any insights would be helpful to help us get to the root cause. Thanks
--
View this message in context:
http://apache-wicket.1842946.n4.nabble.com/Wicket-model-problem-tp4673620p4673662.html
Sent from the Users forum mailing list archive at Nabble.com.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]