Hi!

Perhaps this is stating the obvious since it looks like you know what you are 
doing, but just to be sure:

Does your LoadableDetachableExpressionModel call detach on its “parent” model? 
This is the most frequently occurring source of model leaks I have seen.
Since the last model in the chain is usually attached to a component, that 
model gets detached, but if your “child” model does not call detach on the 
“parent” model and the “parent” model is not attached to a component, it will 
never get detached.

Which model in your example is not getting detached without your override of 
onDetach() in MyPanel? Does it happen to be “abc”?

Met vriendelijke groet,
Kind regards,

Bas

Op 19 februari 2016 bij 15:18:41, gmparker2000 (greg.par...@brovada.com) 
schreef:

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: users-unsubscr...@wicket.apache.org  
For additional commands, e-mail: users-h...@wicket.apache.org  

Reply via email to