wicket-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sven Meier <s...@meiers.net>
Subject Re: question re Component.initModel()
Date Fri, 04 Jan 2013 13:52:19 GMT
Hi,

correct me if I'm wrong, but if B and C are not interested in their 
model (e.g. Panels) then their models will never be accessed.

Sven

On 01/04/2013 02:47 PM, Andrew Geery wrote:
> Thanks for the answer, Sven: I'm not a huge CPM fan either; I find
> them hard to debug and fragile.
>
> I understand your example of needing to get the model for B and C in
> order to get the model for D; however, I guess my ultimate question
> is: given that B and C are, in fact, parents of D, won't their models
> always have to be acquired eventually during the component rendering?
> Isn't all we're really changing just *when* the parent models are
> acquired?
>
> Andrew
>
> On Fri, Jan 4, 2013 at 8:16 AM, Sven Meier <sven@meiers.net> wrote:
>> Hi Andrew,
>>
>>
>>> getModelImpl() is called because getModel() (I think it should be
>>> getDefaultModel() now) could initialize
>>> many inbetween completely useless models. What are these useless inbetween
>>> models? Is that still an issue?
>> this still holds. If you have the following hierarchy:
>>
>> A -> B -> C -> D
>>
>> ... and A has a CompoundPropertyModel and D needs a model. If
>> #getDefaultModel() would be called, B and C would acquire a model even they
>> don't need it.
>>
>> IIRC CompoundPropertyModel has fallen out of favor lately ("too much
>> magic"). Type-safe alternatives are wicket-safemodel or wicket-modelfactory
>> (offering "magic" too ;).
>>
>> I still use CPMs fairly often, but always with option 1).
>>
>> Sven
>>
>>
>>
>> On 01/04/2013 01:12 PM, Andrew Geery wrote:
>>> I wanted to follow up about this.  The nested CompoundPropertyModel
>>> address example in the original email does not work, not because of
>>> the visitor in onConfigure(), but because child models are
>>> (potentially) created before parent models.  For example, in the code
>>> below, there is an "optimization" in the initModel() code that creates
>>> the model backing Label("street1") before the model for the
>>> AddressPanel.  Because of this, Wicket does not know that AddressPanel
>>> is, in fact, a CPM and rather than using it to resolve street1, Wicket
>>> continues to the next parent and resolves street1 against Person.
>>>
>>> There are three options for dealing with this:
>>>
>>> 1) don't use nested CompoundPropertyModels
>>> 2) explicitly call getDefaultModel() on the parent (e.g., in
>>> onInitialize()) before the child models are created
>>> 3) change how the initModel() method works to create the parent model
>>> before creating child models
>>>
>>> I think the best solution is 3 -- I created a JIRA issue with
>>> quickstart for it: https://issues.apache.org/jira/browse/WICKET-4941
>>>
>>> Thanks
>>> Andrew
>>>
>>> On Wed, Dec 19, 2012 at 10:48 AM, Andrew Geery <andrew.geery@gmail.com>
>>> wrote:
>>>> I'm dealing with the issue around a nested CompoundPropertyModel not
>>>> resolving its properties against the correct object.
>>>>
>>>> class Person {
>>>>    Address address;
>>>>     ...
>>>> }
>>>>
>>>> class Address {
>>>>     String street1;
>>>>     ...
>>>> }
>>>>
>>>> class PersonPanel extends Panel {
>>>>     PersonPanel(String id) {
>>>>       super(id); // use cpm of parent
>>>>       add(new AddressPanel("address"));
>>>>     }
>>>> }
>>>>
>>>> class AddressPanel extends Panel {
>>>>
>>>>     AddressPanel(String id) {
>>>>       super(id); // use cpm of parent
>>>>       add(new Label("street1"));
>>>>       ...
>>>>     }
>>>>
>>>> }
>>>>
>>>> When Wicket resolves property "street1" it uses the person object
>>>> rather than the address object.  This has been talked about before
>>>>
>>>> (http://mail-archives.apache.org/mod_mbox/wicket-users/200803.mbox/%3C23eb48360803040850i3022ddbdleca18da7e4f69e8b@mail.gmail.com%3E);
>>>> the solution is to override the initModel() method in the AddressPanel
>>>> class like this:
>>>>
>>>>       @Override
>>>>       protected IModel<?> initModel() {
>>>>           final IModel<?> model = super.initModel(); // returns original
>>>> cpm
>>>>           return new CompoundPropertyModel<>(new PropertyModel<>(model,
>>>> getId()));
>>>>       }
>>>>
>>>> The issue I'm running into now is that I've added a call to
>>>> visitChildren in AddressPanel.onConfigure.
>>>>
>>>> My component() method looks like this:
>>>>
>>>>               public void component(final Component object, final
>>>> IVisit<Void> visit) {
>>>>                   Object obj = object.getDefaultModelObject();
>>>>                   ...
>>>>               }
>>>>
>>>> The issue is that when I call getDefaultModelObject() in the component
>>>> method, the initModel for the AddressPanel has not been called.
>>>>
>>>> The call stack for the Label looks like this:
>>>> Component.getDefaultModelObject() ->
>>>> getDefaultModel() ->
>>>> initModel()
>>>>
>>>> In Component.initModel(), the code iterates through the parents
>>>> looking for a IComponentInheritedModel (CPM).
>>>>
>>>> It does this by calling getModelImpl() on the parent.  This just
>>>> checks if the model is set on the parent; it doesn't actually create
>>>> it if it doesn't exist (i.e., by calling initModel()).  The issue is
>>>> that because initModel() hasn't been called on the AddressPanel, the
>>>> model for it is null and the initModel call on the Label keeps going
>>>> up the hierarchy looking for a CPM.  This would work if rather than
>>>> calling getModelImpl() the code called getDefaultModel() which has the
>>>> effect of calling initModel() if necessary.
>>>>
>>>> There's a code comment saying that the getModelImpl() is called
>>>> because getModel() (I think it should be getDefaultModel() now) could
>>>> initialize many inbetween completely useless models.  What are these
>>>> useless inbetween models?  Is that still an issue?  If it's not, could
>>>> the code be changed to call getDefaultModel() on the parent instead?
>>>>
>>>> The workaround is to make a call to AddressPanel.getDefaultModel()
>>>> before the visitChildren call in onConfigure().
>>>>
>>>> Thanks
>>>> Andrew
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
>>> For additional commands, e-mail: users-help@wicket.apache.org
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
>> For additional commands, e-mail: users-help@wicket.apache.org
>>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Mime
View raw message