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