You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wicket.apache.org by Martin Grigorov <mg...@apache.org> on 2014/01/22 21:12:27 UTC

Markup driven component tree

Hi,

Recently Fridolin Jackstadt shared his approach to "autowire" components -
https://github.com/wicket-acc/wicket-autowire.

I believe this approach can solve two issues:
- duplicate construction of the component tree - once in the markup and
second time in Java code
- auto components available only in the render phase

Here is how I see it:

Any MarkupContainer that wants to use markup-driven-tree must declare the
components as member fields:

private SomeComponent aComponent;

These fields will be instantiated like any other component in Wicket:

aComponent = new SomeComponent(id, ...);

The new thing is that they *won't* be added to a parent component
explicitly/manually.

On Page#onInitialize() the first thing to do it to walk over the component
tree from the page's markup (just like the walk in the rendering related
code) and resolve the missing bits.
I.e. while walking thru the markup tree we will check the Java component
tree (container.get(tagId)). If there is a miss then we search for a member
field that is a component with the same id in the current MarkupContainer,
its (Java) super classes and finally in its (Wicket) parent classes.

This will solve issue #1 (identical trees in Java and markup)
(P.S. Fridolin's code uses @AutoComponent annotation that facilitates
searching by component id, but will duplicate the declaration of the id -
once in the annotation and second time in 'new MyComponent(ID). This is an
implementation detail.)


The second part is not less hard - during the walk over the markup tree
when an autocomponent (e.g. enclosure) is seen Wicket will use the
registered IComponentResolvers to create the Java component and insert it
in the Java tree.
The tricky part here is that any manually added components (like in Wicket
6.x) to the parent of the autocomponent should be moved into the
autocomponent.
For example:

<div wicket:id="a">
   <wicket:enclosure child="b">
      <span wicket:id="b"></span>
      <span wicket:id="c"></span>
   </wicket:enclosure>
</div>

If 'b' and 'c' are added manually to 'a' in the application's Java code:
(a (b,c))

then after the "resolving phase" the tree will be:

a (enclosure(b, c))

so b.getParent() in onInitialize() and later will return the Enclosure, not
'a'.


I don't know very well the MarkupStream APIs but I think all this should be
possible.

WDYT about this approach ?


Martin Grigorov
Wicket Training and Consulting

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
On Thu, Jan 23, 2014 at 8:16 PM, Igor Vaynberg <ig...@gmail.com>wrote:

> On Thu, Jan 23, 2014 at 8:53 AM, Martin Grigorov <mg...@apache.org>
> wrote:
> > On Thu, Jan 23, 2014 at 6:36 PM, Igor Vaynberg <igor.vaynberg@gmail.com
> >wrote:
> >
> >> On Thu, Jan 23, 2014 at 8:20 AM, Martin Grigorov <mg...@apache.org>
> >> wrote:
> >> > Once the markup driven construction is done (just before
> onInitialize())
> >> > the application will have to use the old good add()/addOrReplace().
> >>
> >> yeah, but onInitialize() is there to partially replace the constructor
> >> as a place to add components.
> >>
> >
> > It is perfectly fine to add components later.
> > If markup-driven construction cannot find a component it doesn't blow
> > immediately.
> > It just ignores the rest of the markup stream below the missing
> component.
> > If there is a missing component during rendering then an exception is
> > thrown.
> >
> >
> >>
> >> > The components are already in the MarkupContainer#children data
> >> structure.
> >> > So each field will add extra 8 bytes on 64bit machine (or 4 bytes with
> >> > CompressedOops enabled).
> >>
> >> yes, thats the 8 bytes i was talking about. considering some pages
> >> have easily over a hundred components that adds up.
> >>
> >> > Serialization is the same - the object is written once, with several
> >> > pointers.
> >>
> >> no, serialization will suffer from the same 8 bytes per component
> >> reference issue. that means thats a bunch more bytes to shuffle to and
> >> from disk and also across network when clustered.
> >>
> >
> > Well, I see no other way to find a reference to a component :-/
> > If a page has 1000 components then this is 8k more.
> > 1000 components is a lot. Most pages have much less.
> > I have to check again but recently while working on Memcached based
> > IDataStore I think a pretty simple page serialized was about 60k.
> >
> >
> >>
> >> > I am also not fully sure in the approach but I am experimenting and so
> >> far
> >> > it works well.
> >> > And it is configurable, by default disabled.
> >> > We can advertise it as experimental ?!
> >>
> >> something like this cannot be enabled/disabled. if a component library
> >> uses it then it will fail on applications where this is disabled.
> >>
> >
> > yes, this is true
> > a "workaround" here is each MarkupContainer can declare whether it
> supports
> > markup-driven tree by overriding
> > org.apache.wicket.MarkupContainer#isMarkupDrivenComponentTreeEnabled
> > i.e. the library component can always return true
> >
> >
> >>
> >> also, what happens in situations where ids are not unique? then those
> >> cannot be put into the hierarchy?
> >>
> >> its common to have structure like this:
> >>
> >> <a wicket:id="remove"><span wicket:id="label"></span></a><a
> >> wicket:id="add"><span wicket:id="label"></a>
> >>
> >
> > This should work fine at the moment.
> > Each MarkupContainer instance resolves its own fields/components.
> > I'll add test tomorrow to verify.
>
> not sure what you mean by works fine.
>
> @Auto WebMarkupContainer a,b,c,d;
> a=new Link("remove"); b=new Label("label", "remove"); c=new
> Link("add"); d=new Label("label", "add");
>
> how does wicket know the difference between b and d?
>
> this will get worse with subclasses as now you have to be aware to not
> add any component with the same id used in the class hierarchy...
>

I didn't understand you correctly the first time.
In this case you have two options:
- if you insist on fully markup driven tree then you have to rename the ids
for the labels.
- you can still add manually each label to its link as now. it doesn't make
much sense the web designer to move just the label in the markup and leave
the link

Same is valid for the repeaters. You need unique component instance per
iteration. It doesn't make sense to move an item out of the repeater in the
markup tree ...


>
> -igor
>
>
> >
> >
> >>
> >> another exception is the repeater, unless you create a custom subclass
> >> of Item which no one ever does.
> >>
> >
> > another test to add !
> >
> >
> >>
> >> seems to me there are too many gotchas for all but the most trivial
> >> cases. couple this together with the fact that it has to be enabled as
> >> mentioned above would put me at -0.5 for this for now.
> >>
> >> -igor
> >>
> >> > I will add more use cases/tests soon.
> >> > And caching for the reflection stuff.
> >> >
> >> >
> >> > On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <
> igor.vaynberg@gmail.com
> >> >wrote:
> >> >
> >> >> what about components added in onInitialize() or on onConfigure()?
> >> >>
> >> >> this will also lead to a higher memory/serialization space usage
> since
> >> >> by default you need a field to store the component ref.
> >> >>
> >> >> not sure its worth doing it this way...
> >> >>
> >> >> -igor
> >> >>
> >> >>
> >> >> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <
> mgrigorov@apache.org
> >> >
> >> >> wrote:
> >> >> > Hi,
> >> >> >
> >> >> > Recently Fridolin Jackstadt shared his approach to "autowire"
> >> components
> >> >> -
> >> >> > https://github.com/wicket-acc/wicket-autowire.
> >> >> >
> >> >> > I believe this approach can solve two issues:
> >> >> > - duplicate construction of the component tree - once in the markup
> >> and
> >> >> > second time in Java code
> >> >> > - auto components available only in the render phase
> >> >> >
> >> >> > Here is how I see it:
> >> >> >
> >> >> > Any MarkupContainer that wants to use markup-driven-tree must
> declare
> >> the
> >> >> > components as member fields:
> >> >> >
> >> >> > private SomeComponent aComponent;
> >> >> >
> >> >> > These fields will be instantiated like any other component in
> Wicket:
> >> >> >
> >> >> > aComponent = new SomeComponent(id, ...);
> >> >> >
> >> >> > The new thing is that they *won't* be added to a parent component
> >> >> > explicitly/manually.
> >> >> >
> >> >> > On Page#onInitialize() the first thing to do it to walk over the
> >> >> component
> >> >> > tree from the page's markup (just like the walk in the rendering
> >> related
> >> >> > code) and resolve the missing bits.
> >> >> > I.e. while walking thru the markup tree we will check the Java
> >> component
> >> >> > tree (container.get(tagId)). If there is a miss then we search for
> a
> >> >> member
> >> >> > field that is a component with the same id in the current
> >> >> MarkupContainer,
> >> >> > its (Java) super classes and finally in its (Wicket) parent
> classes.
> >> >> >
> >> >> > This will solve issue #1 (identical trees in Java and markup)
> >> >> > (P.S. Fridolin's code uses @AutoComponent annotation that
> facilitates
> >> >> > searching by component id, but will duplicate the declaration of
> the
> >> id -
> >> >> > once in the annotation and second time in 'new MyComponent(ID).
> This
> >> is
> >> >> an
> >> >> > implementation detail.)
> >> >> >
> >> >> >
> >> >> > The second part is not less hard - during the walk over the markup
> >> tree
> >> >> > when an autocomponent (e.g. enclosure) is seen Wicket will use the
> >> >> > registered IComponentResolvers to create the Java component and
> >> insert it
> >> >> > in the Java tree.
> >> >> > The tricky part here is that any manually added components (like in
> >> >> Wicket
> >> >> > 6.x) to the parent of the autocomponent should be moved into the
> >> >> > autocomponent.
> >> >> > For example:
> >> >> >
> >> >> > <div wicket:id="a">
> >> >> >    <wicket:enclosure child="b">
> >> >> >       <span wicket:id="b"></span>
> >> >> >       <span wicket:id="c"></span>
> >> >> >    </wicket:enclosure>
> >> >> > </div>
> >> >> >
> >> >> > If 'b' and 'c' are added manually to 'a' in the application's Java
> >> code:
> >> >> > (a (b,c))
> >> >> >
> >> >> > then after the "resolving phase" the tree will be:
> >> >> >
> >> >> > a (enclosure(b, c))
> >> >> >
> >> >> > so b.getParent() in onInitialize() and later will return the
> >> Enclosure,
> >> >> not
> >> >> > 'a'.
> >> >> >
> >> >> >
> >> >> > I don't know very well the MarkupStream APIs but I think all this
> >> should
> >> >> be
> >> >> > possible.
> >> >> >
> >> >> > WDYT about this approach ?
> >> >> >
> >> >> >
> >> >> > Martin Grigorov
> >> >> > Wicket Training and Consulting
> >> >>
> >>
>

Re: Markup driven component tree

Posted by Igor Vaynberg <ig...@gmail.com>.
On Thu, Jan 23, 2014 at 8:53 AM, Martin Grigorov <mg...@apache.org> wrote:
> On Thu, Jan 23, 2014 at 6:36 PM, Igor Vaynberg <ig...@gmail.com>wrote:
>
>> On Thu, Jan 23, 2014 at 8:20 AM, Martin Grigorov <mg...@apache.org>
>> wrote:
>> > Once the markup driven construction is done (just before onInitialize())
>> > the application will have to use the old good add()/addOrReplace().
>>
>> yeah, but onInitialize() is there to partially replace the constructor
>> as a place to add components.
>>
>
> It is perfectly fine to add components later.
> If markup-driven construction cannot find a component it doesn't blow
> immediately.
> It just ignores the rest of the markup stream below the missing component.
> If there is a missing component during rendering then an exception is
> thrown.
>
>
>>
>> > The components are already in the MarkupContainer#children data
>> structure.
>> > So each field will add extra 8 bytes on 64bit machine (or 4 bytes with
>> > CompressedOops enabled).
>>
>> yes, thats the 8 bytes i was talking about. considering some pages
>> have easily over a hundred components that adds up.
>>
>> > Serialization is the same - the object is written once, with several
>> > pointers.
>>
>> no, serialization will suffer from the same 8 bytes per component
>> reference issue. that means thats a bunch more bytes to shuffle to and
>> from disk and also across network when clustered.
>>
>
> Well, I see no other way to find a reference to a component :-/
> If a page has 1000 components then this is 8k more.
> 1000 components is a lot. Most pages have much less.
> I have to check again but recently while working on Memcached based
> IDataStore I think a pretty simple page serialized was about 60k.
>
>
>>
>> > I am also not fully sure in the approach but I am experimenting and so
>> far
>> > it works well.
>> > And it is configurable, by default disabled.
>> > We can advertise it as experimental ?!
>>
>> something like this cannot be enabled/disabled. if a component library
>> uses it then it will fail on applications where this is disabled.
>>
>
> yes, this is true
> a "workaround" here is each MarkupContainer can declare whether it supports
> markup-driven tree by overriding
> org.apache.wicket.MarkupContainer#isMarkupDrivenComponentTreeEnabled
> i.e. the library component can always return true
>
>
>>
>> also, what happens in situations where ids are not unique? then those
>> cannot be put into the hierarchy?
>>
>> its common to have structure like this:
>>
>> <a wicket:id="remove"><span wicket:id="label"></span></a><a
>> wicket:id="add"><span wicket:id="label"></a>
>>
>
> This should work fine at the moment.
> Each MarkupContainer instance resolves its own fields/components.
> I'll add test tomorrow to verify.

not sure what you mean by works fine.

@Auto WebMarkupContainer a,b,c,d;
a=new Link("remove"); b=new Label("label", "remove"); c=new
Link("add"); d=new Label("label", "add");

how does wicket know the difference between b and d?

this will get worse with subclasses as now you have to be aware to not
add any component with the same id used in the class hierarchy...

-igor


>
>
>>
>> another exception is the repeater, unless you create a custom subclass
>> of Item which no one ever does.
>>
>
> another test to add !
>
>
>>
>> seems to me there are too many gotchas for all but the most trivial
>> cases. couple this together with the fact that it has to be enabled as
>> mentioned above would put me at -0.5 for this for now.
>>
>> -igor
>>
>> > I will add more use cases/tests soon.
>> > And caching for the reflection stuff.
>> >
>> >
>> > On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <igor.vaynberg@gmail.com
>> >wrote:
>> >
>> >> what about components added in onInitialize() or on onConfigure()?
>> >>
>> >> this will also lead to a higher memory/serialization space usage since
>> >> by default you need a field to store the component ref.
>> >>
>> >> not sure its worth doing it this way...
>> >>
>> >> -igor
>> >>
>> >>
>> >> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <mgrigorov@apache.org
>> >
>> >> wrote:
>> >> > Hi,
>> >> >
>> >> > Recently Fridolin Jackstadt shared his approach to "autowire"
>> components
>> >> -
>> >> > https://github.com/wicket-acc/wicket-autowire.
>> >> >
>> >> > I believe this approach can solve two issues:
>> >> > - duplicate construction of the component tree - once in the markup
>> and
>> >> > second time in Java code
>> >> > - auto components available only in the render phase
>> >> >
>> >> > Here is how I see it:
>> >> >
>> >> > Any MarkupContainer that wants to use markup-driven-tree must declare
>> the
>> >> > components as member fields:
>> >> >
>> >> > private SomeComponent aComponent;
>> >> >
>> >> > These fields will be instantiated like any other component in Wicket:
>> >> >
>> >> > aComponent = new SomeComponent(id, ...);
>> >> >
>> >> > The new thing is that they *won't* be added to a parent component
>> >> > explicitly/manually.
>> >> >
>> >> > On Page#onInitialize() the first thing to do it to walk over the
>> >> component
>> >> > tree from the page's markup (just like the walk in the rendering
>> related
>> >> > code) and resolve the missing bits.
>> >> > I.e. while walking thru the markup tree we will check the Java
>> component
>> >> > tree (container.get(tagId)). If there is a miss then we search for a
>> >> member
>> >> > field that is a component with the same id in the current
>> >> MarkupContainer,
>> >> > its (Java) super classes and finally in its (Wicket) parent classes.
>> >> >
>> >> > This will solve issue #1 (identical trees in Java and markup)
>> >> > (P.S. Fridolin's code uses @AutoComponent annotation that facilitates
>> >> > searching by component id, but will duplicate the declaration of the
>> id -
>> >> > once in the annotation and second time in 'new MyComponent(ID). This
>> is
>> >> an
>> >> > implementation detail.)
>> >> >
>> >> >
>> >> > The second part is not less hard - during the walk over the markup
>> tree
>> >> > when an autocomponent (e.g. enclosure) is seen Wicket will use the
>> >> > registered IComponentResolvers to create the Java component and
>> insert it
>> >> > in the Java tree.
>> >> > The tricky part here is that any manually added components (like in
>> >> Wicket
>> >> > 6.x) to the parent of the autocomponent should be moved into the
>> >> > autocomponent.
>> >> > For example:
>> >> >
>> >> > <div wicket:id="a">
>> >> >    <wicket:enclosure child="b">
>> >> >       <span wicket:id="b"></span>
>> >> >       <span wicket:id="c"></span>
>> >> >    </wicket:enclosure>
>> >> > </div>
>> >> >
>> >> > If 'b' and 'c' are added manually to 'a' in the application's Java
>> code:
>> >> > (a (b,c))
>> >> >
>> >> > then after the "resolving phase" the tree will be:
>> >> >
>> >> > a (enclosure(b, c))
>> >> >
>> >> > so b.getParent() in onInitialize() and later will return the
>> Enclosure,
>> >> not
>> >> > 'a'.
>> >> >
>> >> >
>> >> > I don't know very well the MarkupStream APIs but I think all this
>> should
>> >> be
>> >> > possible.
>> >> >
>> >> > WDYT about this approach ?
>> >> >
>> >> >
>> >> > Martin Grigorov
>> >> > Wicket Training and Consulting
>> >>
>>

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
On Thu, Jan 23, 2014 at 6:36 PM, Igor Vaynberg <ig...@gmail.com>wrote:

> On Thu, Jan 23, 2014 at 8:20 AM, Martin Grigorov <mg...@apache.org>
> wrote:
> > Once the markup driven construction is done (just before onInitialize())
> > the application will have to use the old good add()/addOrReplace().
>
> yeah, but onInitialize() is there to partially replace the constructor
> as a place to add components.
>

It is perfectly fine to add components later.
If markup-driven construction cannot find a component it doesn't blow
immediately.
It just ignores the rest of the markup stream below the missing component.
If there is a missing component during rendering then an exception is
thrown.


>
> > The components are already in the MarkupContainer#children data
> structure.
> > So each field will add extra 8 bytes on 64bit machine (or 4 bytes with
> > CompressedOops enabled).
>
> yes, thats the 8 bytes i was talking about. considering some pages
> have easily over a hundred components that adds up.
>
> > Serialization is the same - the object is written once, with several
> > pointers.
>
> no, serialization will suffer from the same 8 bytes per component
> reference issue. that means thats a bunch more bytes to shuffle to and
> from disk and also across network when clustered.
>

Well, I see no other way to find a reference to a component :-/
If a page has 1000 components then this is 8k more.
1000 components is a lot. Most pages have much less.
I have to check again but recently while working on Memcached based
IDataStore I think a pretty simple page serialized was about 60k.


>
> > I am also not fully sure in the approach but I am experimenting and so
> far
> > it works well.
> > And it is configurable, by default disabled.
> > We can advertise it as experimental ?!
>
> something like this cannot be enabled/disabled. if a component library
> uses it then it will fail on applications where this is disabled.
>

yes, this is true
a "workaround" here is each MarkupContainer can declare whether it supports
markup-driven tree by overriding
org.apache.wicket.MarkupContainer#isMarkupDrivenComponentTreeEnabled
i.e. the library component can always return true


>
> also, what happens in situations where ids are not unique? then those
> cannot be put into the hierarchy?
>
> its common to have structure like this:
>
> <a wicket:id="remove"><span wicket:id="label"></span></a><a
> wicket:id="add"><span wicket:id="label"></a>
>

This should work fine at the moment.
Each MarkupContainer instance resolves its own fields/components.
I'll add test tomorrow to verify.


>
> another exception is the repeater, unless you create a custom subclass
> of Item which no one ever does.
>

another test to add !


>
> seems to me there are too many gotchas for all but the most trivial
> cases. couple this together with the fact that it has to be enabled as
> mentioned above would put me at -0.5 for this for now.
>
> -igor
>
> > I will add more use cases/tests soon.
> > And caching for the reflection stuff.
> >
> >
> > On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <igor.vaynberg@gmail.com
> >wrote:
> >
> >> what about components added in onInitialize() or on onConfigure()?
> >>
> >> this will also lead to a higher memory/serialization space usage since
> >> by default you need a field to store the component ref.
> >>
> >> not sure its worth doing it this way...
> >>
> >> -igor
> >>
> >>
> >> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <mgrigorov@apache.org
> >
> >> wrote:
> >> > Hi,
> >> >
> >> > Recently Fridolin Jackstadt shared his approach to "autowire"
> components
> >> -
> >> > https://github.com/wicket-acc/wicket-autowire.
> >> >
> >> > I believe this approach can solve two issues:
> >> > - duplicate construction of the component tree - once in the markup
> and
> >> > second time in Java code
> >> > - auto components available only in the render phase
> >> >
> >> > Here is how I see it:
> >> >
> >> > Any MarkupContainer that wants to use markup-driven-tree must declare
> the
> >> > components as member fields:
> >> >
> >> > private SomeComponent aComponent;
> >> >
> >> > These fields will be instantiated like any other component in Wicket:
> >> >
> >> > aComponent = new SomeComponent(id, ...);
> >> >
> >> > The new thing is that they *won't* be added to a parent component
> >> > explicitly/manually.
> >> >
> >> > On Page#onInitialize() the first thing to do it to walk over the
> >> component
> >> > tree from the page's markup (just like the walk in the rendering
> related
> >> > code) and resolve the missing bits.
> >> > I.e. while walking thru the markup tree we will check the Java
> component
> >> > tree (container.get(tagId)). If there is a miss then we search for a
> >> member
> >> > field that is a component with the same id in the current
> >> MarkupContainer,
> >> > its (Java) super classes and finally in its (Wicket) parent classes.
> >> >
> >> > This will solve issue #1 (identical trees in Java and markup)
> >> > (P.S. Fridolin's code uses @AutoComponent annotation that facilitates
> >> > searching by component id, but will duplicate the declaration of the
> id -
> >> > once in the annotation and second time in 'new MyComponent(ID). This
> is
> >> an
> >> > implementation detail.)
> >> >
> >> >
> >> > The second part is not less hard - during the walk over the markup
> tree
> >> > when an autocomponent (e.g. enclosure) is seen Wicket will use the
> >> > registered IComponentResolvers to create the Java component and
> insert it
> >> > in the Java tree.
> >> > The tricky part here is that any manually added components (like in
> >> Wicket
> >> > 6.x) to the parent of the autocomponent should be moved into the
> >> > autocomponent.
> >> > For example:
> >> >
> >> > <div wicket:id="a">
> >> >    <wicket:enclosure child="b">
> >> >       <span wicket:id="b"></span>
> >> >       <span wicket:id="c"></span>
> >> >    </wicket:enclosure>
> >> > </div>
> >> >
> >> > If 'b' and 'c' are added manually to 'a' in the application's Java
> code:
> >> > (a (b,c))
> >> >
> >> > then after the "resolving phase" the tree will be:
> >> >
> >> > a (enclosure(b, c))
> >> >
> >> > so b.getParent() in onInitialize() and later will return the
> Enclosure,
> >> not
> >> > 'a'.
> >> >
> >> >
> >> > I don't know very well the MarkupStream APIs but I think all this
> should
> >> be
> >> > possible.
> >> >
> >> > WDYT about this approach ?
> >> >
> >> >
> >> > Martin Grigorov
> >> > Wicket Training and Consulting
> >>
>

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
On Thu, Jan 23, 2014 at 6:36 PM, Igor Vaynberg <ig...@gmail.com>wrote:

> On Thu, Jan 23, 2014 at 8:20 AM, Martin Grigorov <mg...@apache.org>
> wrote:
> > Once the markup driven construction is done (just before onInitialize())
> > the application will have to use the old good add()/addOrReplace().
>
> yeah, but onInitialize() is there to partially replace the constructor
> as a place to add components.
>
> > The components are already in the MarkupContainer#children data
> structure.
> > So each field will add extra 8 bytes on 64bit machine (or 4 bytes with
> > CompressedOops enabled).
>
> yes, thats the 8 bytes i was talking about. considering some pages
> have easily over a hundred components that adds up.
>
> > Serialization is the same - the object is written once, with several
> > pointers.
>
> no, serialization will suffer from the same 8 bytes per component
> reference issue. that means thats a bunch more bytes to shuffle to and
> from disk and also across network when clustered.
>

I have an idea how to solve the issue with the extra bytes. it should solve
the problem without adding any new bytes
I'll try it later today



>
> > I am also not fully sure in the approach but I am experimenting and so
> far
> > it works well.
> > And it is configurable, by default disabled.
> > We can advertise it as experimental ?!
>
> something like this cannot be enabled/disabled. if a component library
> uses it then it will fail on applications where this is disabled.
>
> also, what happens in situations where ids are not unique? then those
> cannot be put into the hierarchy?
>
> its common to have structure like this:
>
> <a wicket:id="remove"><span wicket:id="label"></span></a><a
> wicket:id="add"><span wicket:id="label"></a>
>
> another exception is the repeater, unless you create a custom subclass
> of Item which no one ever does.
>
> seems to me there are too many gotchas for all but the most trivial
> cases. couple this together with the fact that it has to be enabled as
> mentioned above would put me at -0.5 for this for now.
>
> -igor
>
> > I will add more use cases/tests soon.
> > And caching for the reflection stuff.
> >
> >
> > On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <igor.vaynberg@gmail.com
> >wrote:
> >
> >> what about components added in onInitialize() or on onConfigure()?
> >>
> >> this will also lead to a higher memory/serialization space usage since
> >> by default you need a field to store the component ref.
> >>
> >> not sure its worth doing it this way...
> >>
> >> -igor
> >>
> >>
> >> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <mgrigorov@apache.org
> >
> >> wrote:
> >> > Hi,
> >> >
> >> > Recently Fridolin Jackstadt shared his approach to "autowire"
> components
> >> -
> >> > https://github.com/wicket-acc/wicket-autowire.
> >> >
> >> > I believe this approach can solve two issues:
> >> > - duplicate construction of the component tree - once in the markup
> and
> >> > second time in Java code
> >> > - auto components available only in the render phase
> >> >
> >> > Here is how I see it:
> >> >
> >> > Any MarkupContainer that wants to use markup-driven-tree must declare
> the
> >> > components as member fields:
> >> >
> >> > private SomeComponent aComponent;
> >> >
> >> > These fields will be instantiated like any other component in Wicket:
> >> >
> >> > aComponent = new SomeComponent(id, ...);
> >> >
> >> > The new thing is that they *won't* be added to a parent component
> >> > explicitly/manually.
> >> >
> >> > On Page#onInitialize() the first thing to do it to walk over the
> >> component
> >> > tree from the page's markup (just like the walk in the rendering
> related
> >> > code) and resolve the missing bits.
> >> > I.e. while walking thru the markup tree we will check the Java
> component
> >> > tree (container.get(tagId)). If there is a miss then we search for a
> >> member
> >> > field that is a component with the same id in the current
> >> MarkupContainer,
> >> > its (Java) super classes and finally in its (Wicket) parent classes.
> >> >
> >> > This will solve issue #1 (identical trees in Java and markup)
> >> > (P.S. Fridolin's code uses @AutoComponent annotation that facilitates
> >> > searching by component id, but will duplicate the declaration of the
> id -
> >> > once in the annotation and second time in 'new MyComponent(ID). This
> is
> >> an
> >> > implementation detail.)
> >> >
> >> >
> >> > The second part is not less hard - during the walk over the markup
> tree
> >> > when an autocomponent (e.g. enclosure) is seen Wicket will use the
> >> > registered IComponentResolvers to create the Java component and
> insert it
> >> > in the Java tree.
> >> > The tricky part here is that any manually added components (like in
> >> Wicket
> >> > 6.x) to the parent of the autocomponent should be moved into the
> >> > autocomponent.
> >> > For example:
> >> >
> >> > <div wicket:id="a">
> >> >    <wicket:enclosure child="b">
> >> >       <span wicket:id="b"></span>
> >> >       <span wicket:id="c"></span>
> >> >    </wicket:enclosure>
> >> > </div>
> >> >
> >> > If 'b' and 'c' are added manually to 'a' in the application's Java
> code:
> >> > (a (b,c))
> >> >
> >> > then after the "resolving phase" the tree will be:
> >> >
> >> > a (enclosure(b, c))
> >> >
> >> > so b.getParent() in onInitialize() and later will return the
> Enclosure,
> >> not
> >> > 'a'.
> >> >
> >> >
> >> > I don't know very well the MarkupStream APIs but I think all this
> should
> >> be
> >> > possible.
> >> >
> >> > WDYT about this approach ?
> >> >
> >> >
> >> > Martin Grigorov
> >> > Wicket Training and Consulting
> >>
>

Re: Markup driven component tree

Posted by Igor Vaynberg <ig...@gmail.com>.
On Thu, Jan 23, 2014 at 8:20 AM, Martin Grigorov <mg...@apache.org> wrote:
> Once the markup driven construction is done (just before onInitialize())
> the application will have to use the old good add()/addOrReplace().

yeah, but onInitialize() is there to partially replace the constructor
as a place to add components.

> The components are already in the MarkupContainer#children data structure.
> So each field will add extra 8 bytes on 64bit machine (or 4 bytes with
> CompressedOops enabled).

yes, thats the 8 bytes i was talking about. considering some pages
have easily over a hundred components that adds up.

> Serialization is the same - the object is written once, with several
> pointers.

no, serialization will suffer from the same 8 bytes per component
reference issue. that means thats a bunch more bytes to shuffle to and
from disk and also across network when clustered.

> I am also not fully sure in the approach but I am experimenting and so far
> it works well.
> And it is configurable, by default disabled.
> We can advertise it as experimental ?!

something like this cannot be enabled/disabled. if a component library
uses it then it will fail on applications where this is disabled.

also, what happens in situations where ids are not unique? then those
cannot be put into the hierarchy?

its common to have structure like this:

<a wicket:id="remove"><span wicket:id="label"></span></a><a
wicket:id="add"><span wicket:id="label"></a>

another exception is the repeater, unless you create a custom subclass
of Item which no one ever does.

seems to me there are too many gotchas for all but the most trivial
cases. couple this together with the fact that it has to be enabled as
mentioned above would put me at -0.5 for this for now.

-igor

> I will add more use cases/tests soon.
> And caching for the reflection stuff.
>
>
> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <ig...@gmail.com>wrote:
>
>> what about components added in onInitialize() or on onConfigure()?
>>
>> this will also lead to a higher memory/serialization space usage since
>> by default you need a field to store the component ref.
>>
>> not sure its worth doing it this way...
>>
>> -igor
>>
>>
>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <mg...@apache.org>
>> wrote:
>> > Hi,
>> >
>> > Recently Fridolin Jackstadt shared his approach to "autowire" components
>> -
>> > https://github.com/wicket-acc/wicket-autowire.
>> >
>> > I believe this approach can solve two issues:
>> > - duplicate construction of the component tree - once in the markup and
>> > second time in Java code
>> > - auto components available only in the render phase
>> >
>> > Here is how I see it:
>> >
>> > Any MarkupContainer that wants to use markup-driven-tree must declare the
>> > components as member fields:
>> >
>> > private SomeComponent aComponent;
>> >
>> > These fields will be instantiated like any other component in Wicket:
>> >
>> > aComponent = new SomeComponent(id, ...);
>> >
>> > The new thing is that they *won't* be added to a parent component
>> > explicitly/manually.
>> >
>> > On Page#onInitialize() the first thing to do it to walk over the
>> component
>> > tree from the page's markup (just like the walk in the rendering related
>> > code) and resolve the missing bits.
>> > I.e. while walking thru the markup tree we will check the Java component
>> > tree (container.get(tagId)). If there is a miss then we search for a
>> member
>> > field that is a component with the same id in the current
>> MarkupContainer,
>> > its (Java) super classes and finally in its (Wicket) parent classes.
>> >
>> > This will solve issue #1 (identical trees in Java and markup)
>> > (P.S. Fridolin's code uses @AutoComponent annotation that facilitates
>> > searching by component id, but will duplicate the declaration of the id -
>> > once in the annotation and second time in 'new MyComponent(ID). This is
>> an
>> > implementation detail.)
>> >
>> >
>> > The second part is not less hard - during the walk over the markup tree
>> > when an autocomponent (e.g. enclosure) is seen Wicket will use the
>> > registered IComponentResolvers to create the Java component and insert it
>> > in the Java tree.
>> > The tricky part here is that any manually added components (like in
>> Wicket
>> > 6.x) to the parent of the autocomponent should be moved into the
>> > autocomponent.
>> > For example:
>> >
>> > <div wicket:id="a">
>> >    <wicket:enclosure child="b">
>> >       <span wicket:id="b"></span>
>> >       <span wicket:id="c"></span>
>> >    </wicket:enclosure>
>> > </div>
>> >
>> > If 'b' and 'c' are added manually to 'a' in the application's Java code:
>> > (a (b,c))
>> >
>> > then after the "resolving phase" the tree will be:
>> >
>> > a (enclosure(b, c))
>> >
>> > so b.getParent() in onInitialize() and later will return the Enclosure,
>> not
>> > 'a'.
>> >
>> >
>> > I don't know very well the MarkupStream APIs but I think all this should
>> be
>> > possible.
>> >
>> > WDYT about this approach ?
>> >
>> >
>> > Martin Grigorov
>> > Wicket Training and Consulting
>>

Re: Markup driven component tree

Posted by Sven Meier <sv...@meiers.net>.
Thank your for your efforts so far, Martin.

I'll try to look into your recent commits this week.

Regards
Sven

On 01/27/2014 02:14 PM, Martin Grigorov wrote:
> I am suspending my work on this because I think there is not enough
> interest in this feature at the moment.
>
> Martin Grigorov
> Wicket Training and Consulting
>
>
> On Mon, Jan 27, 2014 at 10:07 AM, Martin Grigorov <mg...@apache.org>wrote:
>
>> Reading the archives for Igor's work on "component queueing" I see
>>
>> Igor Vaynberg<https://issues.apache.org/jira/secure/ViewProfile.jspa?name=ivaynberg> added
>> a comment - 09/Jul/11 23:39
>>
>> @Juergen, right now your tests only test for rendering, but they should
>> also test that before queued component's oninitialize is called the
>> component is already a child of the correct parent.
>>
>>   https://issues.apache.org/jira/browse/WICKET-3335
>>
>>
>> This means that
>> org.apache.wicket.application.IComponentInitializationListener cannot be
>> used. The tree (re)building should happen *before *components'
>> #onInitialize() and .IComponentInitializationListener#onInitialize() is
>> called *after*.
>>
>> Martin Grigorov
>> Wicket Training and Consulting
>>
>>
>> On Fri, Jan 24, 2014 at 2:22 PM, Martin Grigorov <mg...@apache.org>wrote:
>>
>>> I've added alternative ways to use MarkupDrivenComponentTreeBuilder:
>>> - with org.apache.wicket.MarkupDrivenTreeInitializionListener
>>> - with org.apache.wicket.MarkupDrivenComponentTreeBehavior#onConfigure
>>>
>>> Both of them do not check the configuration setting whether markup driven
>>> tree construction is enabled for now.
>>>
>>> The approach with MarkupDrivenTreeInitializionListener works the same way
>>> as the "inlined" version. The component tree rebuild is activated *after*
>>> all Component#onInitialize().
>>>
>>> The approach with MarkupDrivenComponentTreeBehavior uses #onConfigure().
>>> Here I had to change Enclosure class - the child component resolving should
>>> be done as late as possible just before the rendering phase starts.
>>>
>>> Martin Grigorov
>>> Wicket Training and Consulting
>>>
>>>
>>> On Fri, Jan 24, 2014 at 11:47 AM, Martin Grigorov <mg...@apache.org>wrote:
>>>
>>>> OK, the new impl is committed.
>>>> Now MarkupContainer has #enqueue(Component...) method that adds
>>>> components into a list.
>>>> Later org.apache.wicket.ComponentTreeBuilder#rebuild() uses the list,
>>>> and finally the list is null-yfied in #onDetach() so it is not serialized
>>>> and not available for the next requests. I guess the null-yfing can be done
>>>> earlier so even the first request have the extra bytes after the rebuild of
>>>> the tree.
>>>>
>>>> No need of @Auto anymore.
>>>>
>>>> Martin Grigorov
>>>> Wicket Training and Consulting
>>>>
>>>>
>>>> On Fri, Jan 24, 2014 at 10:39 AM, Martin Grigorov <mg...@apache.org>wrote:
>>>>
>>>>>
>>>>> On Fri, Jan 24, 2014 at 9:48 AM, Sven Meier <sv...@meiers.net> wrote:
>>>>>
>>>>>>> per-component basis - yes, as I explained earlier this is possible
>>>>>> with the current impl
>>>>>>
>>>>>> I must have missed that. Is there an example in the branch?
>>>>>>
>>>>> See
>>>>> https://github.com/apache/wicket/blob/markup-driven-component-tree/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java?source=c#L1886
>>>>> There is no test yet.
>>>>>
>>>>>
>>>>>> I don't understand why there's need for an @Auto annotation. Why would
>>>>>> some components be annotated and some not?
>>>>>
>>>>> The annotation was needed to be able to find the component faster.
>>>>> I.e. check only annotated fields. If @Auto(id=...) then use the id to
>>>>> match against the component tag id.
>>>>>
>>>>> But with my new idea, the one that will solve the issue with the extra
>>>>> bytes, this won't be needed anymore.
>>>>> Stay tuned.
>>>>>
>>>>>
>>>>>>
>>>>>>   behaviors don't have hooks for onInitialize()
>>>>>> It could be done in #onConfigue(), that's early enough.
>>>>>
>>>>> The problem is that it is called for each request.
>>>>> For now I think there is no need to rebuild the component tree for each
>>>>> request, so we will have to use a guard (e.g. boolean field in the
>>>>> component).
>>>>> I will consider it.
>>>>>
>>>>>
>>>>>>
>>>>>>   Additionally I think using Behavior will add a bit more bytes to each
>>>>>>> component than the current solution
>>>>>>>
>>>>>> I don't think that is a problem: IMHO it's important to make this
>>>>>> feature optional, so when users don't use it then they do not pay a price.
>>>>>>
>>>>>> Regards
>>>>>> Sven
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 01/24/2014 06:35 AM, Martin Grigorov wrote:
>>>>>>
>>>>>>> On Fri, Jan 24, 2014 at 12:04 AM, Sven Meier <sv...@meiers.net> wrote:
>>>>>>>
>>>>>>>   Hi,
>>>>>>>> I don't think we're heading the right direction with this and I
>>>>>>>> wouldn't
>>>>>>>> advertise it as anything yet.
>>>>>>>>
>>>>>>>>   I'd like to advertise it anyhow now just to have more people
>>>>>>> feeding me
>>>>>>> with stoppers, as you and Igor do. Thanks! :-)
>>>>>>>
>>>>>>>
>>>>>>>   There are more questions to come but here is one upfront:
>>>>>>>>
>>>>>>>>   And it is configurable, by default disabled.
>>>>>>>> As Igor has written, this does not work with component libraries
>>>>>>>> which
>>>>>>>> depend on the new feature.
>>>>>>>> Couldn't this feature be enabled/disabled on a per-component basis?
>>>>>>>> Why
>>>>>>>> not make it a behavior that you can attach to components if you want
>>>>>>>> to use
>>>>>>>> automatic resolving/rearranging of its children?
>>>>>>>>
>>>>>>>>   - per-component basis - yes, as I explained earlier this is
>>>>>>> possible with
>>>>>>> the current impl
>>>>>>> - behaviors don't have hooks for onInitialize()
>>>>>>> After Igor's feedback I think onAfterInitialize() is what is needed,
>>>>>>> so
>>>>>>> apps can use onInitialize() as a complement to the constructor
>>>>>>> Additionally I think using Behavior will add a bit more bytes to each
>>>>>>> component than the current solution
>>>>>>>
>>>>>>>
>>>>>>>   Regards
>>>>>>>> Sven
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On 01/23/2014 05:20 PM, Martin Grigorov wrote:
>>>>>>>>
>>>>>>>>   Once the markup driven construction is done (just before
>>>>>>>>> onInitialize())
>>>>>>>>> the application will have to use the old good add()/addOrReplace().
>>>>>>>>>
>>>>>>>>> The components are already in the MarkupContainer#children data
>>>>>>>>> structure.
>>>>>>>>> So each field will add extra 8 bytes on 64bit machine (or 4 bytes
>>>>>>>>> with
>>>>>>>>> CompressedOops enabled).
>>>>>>>>> Serialization is the same - the object is written once, with several
>>>>>>>>> pointers.
>>>>>>>>>
>>>>>>>>> I am also not fully sure in the approach but I am experimenting and
>>>>>>>>> so far
>>>>>>>>> it works well.
>>>>>>>>> And it is configurable, by default disabled.
>>>>>>>>> We can advertise it as experimental ?!
>>>>>>>>>
>>>>>>>>> I will add more use cases/tests soon.
>>>>>>>>> And caching for the reflection stuff.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <
>>>>>>>>> igor.vaynberg@gmail.com>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>    what about components added in onInitialize() or on onConfigure()?
>>>>>>>>>
>>>>>>>>>> this will also lead to a higher memory/serialization space usage
>>>>>>>>>> since
>>>>>>>>>> by default you need a field to store the component ref.
>>>>>>>>>>
>>>>>>>>>> not sure its worth doing it this way...
>>>>>>>>>>
>>>>>>>>>> -igor
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <
>>>>>>>>>> mgrigorov@apache.org>
>>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>>   Hi,
>>>>>>>>>>> Recently Fridolin Jackstadt shared his approach to "autowire"
>>>>>>>>>>> components
>>>>>>>>>>>
>>>>>>>>>>>   -
>>>>>>>>>>   https://github.com/wicket-acc/wicket-autowire.
>>>>>>>>>>> I believe this approach can solve two issues:
>>>>>>>>>>> - duplicate construction of the component tree - once in the
>>>>>>>>>>> markup and
>>>>>>>>>>> second time in Java code
>>>>>>>>>>> - auto components available only in the render phase
>>>>>>>>>>>
>>>>>>>>>>> Here is how I see it:
>>>>>>>>>>>
>>>>>>>>>>> Any MarkupContainer that wants to use markup-driven-tree must
>>>>>>>>>>> declare
>>>>>>>>>>> the
>>>>>>>>>>> components as member fields:
>>>>>>>>>>>
>>>>>>>>>>> private SomeComponent aComponent;
>>>>>>>>>>>
>>>>>>>>>>> These fields will be instantiated like any other component in
>>>>>>>>>>> Wicket:
>>>>>>>>>>>
>>>>>>>>>>> aComponent = new SomeComponent(id, ...);
>>>>>>>>>>>
>>>>>>>>>>> The new thing is that they *won't* be added to a parent component
>>>>>>>>>>> explicitly/manually.
>>>>>>>>>>>
>>>>>>>>>>> On Page#onInitialize() the first thing to do it to walk over the
>>>>>>>>>>>
>>>>>>>>>>>   component
>>>>>>>>>>   tree from the page's markup (just like the walk in the rendering
>>>>>>>>>>> related
>>>>>>>>>>> code) and resolve the missing bits.
>>>>>>>>>>> I.e. while walking thru the markup tree we will check the Java
>>>>>>>>>>> component
>>>>>>>>>>> tree (container.get(tagId)). If there is a miss then we search
>>>>>>>>>>> for a
>>>>>>>>>>>
>>>>>>>>>>>   member
>>>>>>>>>>   field that is a component with the same id in the current
>>>>>>>>>>>   MarkupContainer,
>>>>>>>>>>   its (Java) super classes and finally in its (Wicket) parent
>>>>>>>>>>> classes.
>>>>>>>>>>>
>>>>>>>>>>> This will solve issue #1 (identical trees in Java and markup)
>>>>>>>>>>> (P.S. Fridolin's code uses @AutoComponent annotation that
>>>>>>>>>>> facilitates
>>>>>>>>>>> searching by component id, but will duplicate the declaration of
>>>>>>>>>>> the id
>>>>>>>>>>> -
>>>>>>>>>>> once in the annotation and second time in 'new MyComponent(ID).
>>>>>>>>>>> This is
>>>>>>>>>>>
>>>>>>>>>>>   an
>>>>>>>>>>   implementation detail.)
>>>>>>>>>>>
>>>>>>>>>>> The second part is not less hard - during the walk over the
>>>>>>>>>>> markup tree
>>>>>>>>>>> when an autocomponent (e.g. enclosure) is seen Wicket will use the
>>>>>>>>>>> registered IComponentResolvers to create the Java component and
>>>>>>>>>>> insert
>>>>>>>>>>> it
>>>>>>>>>>> in the Java tree.
>>>>>>>>>>> The tricky part here is that any manually added components (like
>>>>>>>>>>> in
>>>>>>>>>>>
>>>>>>>>>>>   Wicket
>>>>>>>>>>   6.x) to the parent of the autocomponent should be moved into the
>>>>>>>>>>> autocomponent.
>>>>>>>>>>> For example:
>>>>>>>>>>>
>>>>>>>>>>> <div wicket:id="a">
>>>>>>>>>>>       <wicket:enclosure child="b">
>>>>>>>>>>>          <span wicket:id="b"></span>
>>>>>>>>>>>          <span wicket:id="c"></span>
>>>>>>>>>>>       </wicket:enclosure>
>>>>>>>>>>> </div>
>>>>>>>>>>>
>>>>>>>>>>> If 'b' and 'c' are added manually to 'a' in the application's
>>>>>>>>>>> Java code:
>>>>>>>>>>> (a (b,c))
>>>>>>>>>>>
>>>>>>>>>>> then after the "resolving phase" the tree will be:
>>>>>>>>>>>
>>>>>>>>>>> a (enclosure(b, c))
>>>>>>>>>>>
>>>>>>>>>>> so b.getParent() in onInitialize() and later will return the
>>>>>>>>>>> Enclosure,
>>>>>>>>>>>
>>>>>>>>>>>   not
>>>>>>>>>>   'a'.
>>>>>>>>>>>
>>>>>>>>>>> I don't know very well the MarkupStream APIs but I think all this
>>>>>>>>>>> should
>>>>>>>>>>>
>>>>>>>>>>>   be
>>>>>>>>>>   possible.
>>>>>>>>>>> WDYT about this approach ?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Martin Grigorov
>>>>>>>>>>> Wicket Training and Consulting
>>>>>>>>>>>
>>>>>>>>>>>


Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
I just merged from master and ran mvn clean install locally and many tests
fail

So I reverted to

commit 3a3e32a597aa312f97cc588a66780783cd0eb9ed
Author: Igor Vaynberg <ig...@gmail.com>
Date:   Sat Feb 15 21:56:18 2014 -0800

    dequeue docs

and the build breaks the same way.
I will debug it.

Martin Grigorov
Wicket Training and Consulting


On Mon, Feb 17, 2014 at 4:48 AM, Igor Vaynberg <ig...@gmail.com>wrote:

> i think the implementation is good enough to be merged into master
> now. it supports:
>
> * dequeuing algorithm that delegates to components so subclasses can
> override (this is how repeaters and borders support it)
> * support for all major constructs: panels, borders, repeaters
> * support for auto component hierarchy - they are dequeued and queued
> up children are placed as the children of auto components - this makes
> things like enclosures trivial to implement where as before they were
> fairy complex
> * performance comparable to adding, still some room for improvement
> with clever/efficient data structures maybe, but i dont think its
> needed...
>
> todo:
>
> * fragments - should be trivial, possibly as trivial as letting it
> implement IQueueRegion
> * check markup inheritance works on pages, panels, fragments.
> * examples
> * update to the guide
>
> -igor
>
>
>
>
>
> On Fri, Feb 14, 2014 at 8:36 AM, Igor Vaynberg <ig...@gmail.com>
> wrote:
> > i am reworking the implementation a bit to properly support borders
> > and repeaters by delegating to components...will check it in when i
> > have it working...
> >
> > -igor
> >
> >
> > On Fri, Feb 14, 2014 at 7:26 AM, Martin Grigorov <mg...@apache.org>
> wrote:
> >> On Mon, Feb 10, 2014 at 6:01 PM, Igor Vaynberg <igor.vaynberg@gmail.com
> >wrote:
> >>
> >>> On Mon, Feb 10, 2014 at 6:26 AM, Martin Grigorov <mgrigorov@apache.org
> >
> >>> wrote:
> >>> >
> >>> > On Mon, Feb 10, 2014 at 9:43 AM, Igor Vaynberg <
> igor.vaynberg@gmail.com
> >>> >wrote:
> >>> >
> >>> > > i just pushed my new idea into sandbox/component-queueing-2
> >>> > >
> >>> > > the way this works now is instead of doing it in onInitialize()
> and in
> >>> > > onConfigure() and all the other places dequeuing now works
> >>> progressively.
> >>> > > upon a change (container.queue() or component.add()) a dequeue
> will be
> >>> > > tried.
> >>> > >
> >>> > > it even works well with resolved components like enclosures. for
> such
> >>> > > components the markup of page/panel is traversed in onInitialize()
> and
> >>> all
> >>> > > auto components are placed into the queue. later as components are
> >>> > > added/queued these components will be placed into the correct
> place in
> >>> the
> >>> > > hierarchy. if queue() is used children of these components will be
> >>> placed
> >>> > > under them in correct hierarchy place. this is a big win for using
> >>> queueing
> >>> > > over adding.
> >>> > >
> >>> > > repeaters also work. the repeater items themselves have to be
> added to
> >>> the
> >>> > > repeater, but item's children can be queued. this is not a problem
> >>> since
> >>> > > items are mostly added by framework classes.
> >>> > >
> >>> > > Borders do not yet work mainly because i havent tried to make them
> >>> work.
> >>> > > the tricky part there is to keep the border and BorderBody queues
> >>> separate.
> >>> > >
> >>> >
> >>> > I've added some code to support it but it needs more work.
> >>> > See my response to the commit notification email of my changes.
> >>>
> >>
> >> Basic usage of Border is now supported.
> >> I have added a test with nested Borders and it fails.
> >> Please check
> >>
> org.apache.wicket.queueing.ComponentQueueingTest#dequeueWithNestedBorders
> >>
> >>
> >>>  >
> >>> > Also we have BorderBehavior and BorderPanel.
> >>> > I think (almost) no one uses those but they exist.
> >>>
> >>> imho we can nuke these two things from 7. they dont look very useful.
> >>> probably added just because we could.
> >>>
> >>> > > InlineEnclosures do not yet work because the code for figuring out
> the
> >>> > > value of the child attribute is really convoluted for the simple
> thing
> >>> its
> >>> > > supposed to do and i didnt bother parsing it. Should be very
> similar
> >>> to how
> >>> > > EnclosureHandler works.
> >>> > >
> >>> >
> >>> > Done.
> >>>
> >>> thanks.
> >>>
> >>> > > the performance is good. there is ComponentQueueingPerformanceTest
> >>> with a
> >>> > > disabled test. give it a go and let me know the results. on my box
> >>> queuing
> >>> > > had under 10% overhead, which is acceptable. I also have some
> ideas on
> >>> how
> >>> > > to optimize that further by trading cpu for a bit more memory, but
> not
> >>> sure
> >>> > >
> >>> >
> >>> > In my branch on this topic I used HashMap instead of array. The
> lookup is
> >>> > faster. Not sure how much memory overhead there is.
> >>>
> >>> yeah. havent had time to profile it yet. there are some memory
> >>> efficient hashmaps floating around, maybe we can adapt one of them.
> >>>
> >>
> >> I've added ComponentQueue2 based on HashMap with the same initial
> capacity
> >> (8) and
> >> loadFactor 1.
> >>
> >> wicket-util has MicroMap for 1entry and MiniMap for fixed size entries
> but
> >> it doesn't use hash function so it iterates over the entries as we do
> over
> >> the array in ComponentQueue(1).
> >>
> >> With ComponentQueue2 the map will start with capacity 8 and will double
> >> when the ninth is to be added, as in ComponentQueue. But it won't shrink
> >> until it becomes with size 0.
> >> org.apache.wicket.queueing.ComponentQueueingPerformanceTest gives almost
> >> the same results for both impls here:
> >> add duration: ~2500
> >> queue duration: ~2400
> >>
> >> memory wise Intellij IDEA reports:
> >> - with ComponentQueue: max memory 88Mb
> >> - with ComponentQueue2: max memory 154Mb
> >>
> >> so ComponentQueue is a winner here. I've added ComponentQueue2 just in
> case
> >> someone wants to try to optimize it
> >>
> >>
> >>>
> >>> -igor
> >>>
> >>> > > if its needed since the overhead is low and because its only
> present
> >>> when
> >>> > > queuing is used. also the measurements are not too accurate because
> >>> most of
> >>> > > the time is spent initializing and tearing down a WicketTester
> >>> instance.
> >>> > >
> >>> > > memory overhead is also low, two slots (one of which can/should be
> >>> > > converted to a flag) are added to MarkupContainer.
> >>> > >
> >>> > > see ComponentQueuing test for some examples. i would appreciate
> some
> >>> help
> >>> > > getting Border and InlineEnclosure working if someone has time.
> >>> > >
> >>> > > look over this and lets discuss if/when we should merge it into
> master.
> >>> > >
> >>> > > -igor
> >>>
>

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
On Tue, Feb 18, 2014 at 3:29 PM, Martin Grigorov <mg...@apache.org>wrote:

>
>
>
> On Mon, Feb 17, 2014 at 5:48 AM, Igor Vaynberg <ig...@gmail.com>wrote:
>
>> i think the implementation is good enough to be merged into master
>> now. it supports:
>>
>
> I am still not able to fix the tests
> I will need more time to get acquaint with the new code to be able to
> maintain it
>
>
>>
>> * dequeuing algorithm that delegates to components so subclasses can
>> override (this is how repeaters and borders support it)
>> * support for all major constructs: panels, borders, repeaters
>> * support for auto component hierarchy - they are dequeued and queued
>> up children are placed as the children of auto components - this makes
>> things like enclosures trivial to implement where as before they were
>> fairy complex
>> * performance comparable to adding, still some room for improvement
>> with clever/efficient data structures maybe, but i dont think its
>> needed...
>>
>
> I see regression here
> last time I ran the performance test it needed 9s to run and used 88Mb
> memory
> now the time is 11s and the memory is 201Mb
>

the memory can be ignored. I've rerun the test several times and IDEA shows
very different things - from 65Mb to 365Mb

but the needed time is 11-12s, was 9s last Friday
the sysout is: add duration: 3285 queue duration: 3203 , was ~2400 last
Friday


>
>
>>
>> todo:
>>
>> * fragments - should be trivial, possibly as trivial as letting it
>> implement IQueueRegion
>> * check markup inheritance works on pages, panels, fragments.
>> * examples
>> * update to the guide
>>
>> -igor
>>
>>
>>
>>
>>
>> On Fri, Feb 14, 2014 at 8:36 AM, Igor Vaynberg <ig...@gmail.com>
>> wrote:
>> > i am reworking the implementation a bit to properly support borders
>> > and repeaters by delegating to components...will check it in when i
>> > have it working...
>> >
>> > -igor
>> >
>> >
>> > On Fri, Feb 14, 2014 at 7:26 AM, Martin Grigorov <mg...@apache.org>
>> wrote:
>> >> On Mon, Feb 10, 2014 at 6:01 PM, Igor Vaynberg <
>> igor.vaynberg@gmail.com>wrote:
>> >>
>> >>> On Mon, Feb 10, 2014 at 6:26 AM, Martin Grigorov <
>> mgrigorov@apache.org>
>> >>> wrote:
>> >>> >
>> >>> > On Mon, Feb 10, 2014 at 9:43 AM, Igor Vaynberg <
>> igor.vaynberg@gmail.com
>> >>> >wrote:
>> >>> >
>> >>> > > i just pushed my new idea into sandbox/component-queueing-2
>> >>> > >
>> >>> > > the way this works now is instead of doing it in onInitialize()
>> and in
>> >>> > > onConfigure() and all the other places dequeuing now works
>> >>> progressively.
>> >>> > > upon a change (container.queue() or component.add()) a dequeue
>> will be
>> >>> > > tried.
>> >>> > >
>> >>> > > it even works well with resolved components like enclosures. for
>> such
>> >>> > > components the markup of page/panel is traversed in
>> onInitialize() and
>> >>> all
>> >>> > > auto components are placed into the queue. later as components are
>> >>> > > added/queued these components will be placed into the correct
>> place in
>> >>> the
>> >>> > > hierarchy. if queue() is used children of these components will be
>> >>> placed
>> >>> > > under them in correct hierarchy place. this is a big win for using
>> >>> queueing
>> >>> > > over adding.
>> >>> > >
>> >>> > > repeaters also work. the repeater items themselves have to be
>> added to
>> >>> the
>> >>> > > repeater, but item's children can be queued. this is not a problem
>> >>> since
>> >>> > > items are mostly added by framework classes.
>> >>> > >
>> >>> > > Borders do not yet work mainly because i havent tried to make them
>> >>> work.
>> >>> > > the tricky part there is to keep the border and BorderBody queues
>> >>> separate.
>> >>> > >
>> >>> >
>> >>> > I've added some code to support it but it needs more work.
>> >>> > See my response to the commit notification email of my changes.
>> >>>
>> >>
>> >> Basic usage of Border is now supported.
>> >> I have added a test with nested Borders and it fails.
>> >> Please check
>> >>
>> org.apache.wicket.queueing.ComponentQueueingTest#dequeueWithNestedBorders
>> >>
>> >>
>> >>>  >
>> >>> > Also we have BorderBehavior and BorderPanel.
>> >>> > I think (almost) no one uses those but they exist.
>> >>>
>> >>> imho we can nuke these two things from 7. they dont look very useful.
>> >>> probably added just because we could.
>> >>>
>> >>> > > InlineEnclosures do not yet work because the code for figuring
>> out the
>> >>> > > value of the child attribute is really convoluted for the simple
>> thing
>> >>> its
>> >>> > > supposed to do and i didnt bother parsing it. Should be very
>> similar
>> >>> to how
>> >>> > > EnclosureHandler works.
>> >>> > >
>> >>> >
>> >>> > Done.
>> >>>
>> >>> thanks.
>> >>>
>> >>> > > the performance is good. there is ComponentQueueingPerformanceTest
>> >>> with a
>> >>> > > disabled test. give it a go and let me know the results. on my box
>> >>> queuing
>> >>> > > had under 10% overhead, which is acceptable. I also have some
>> ideas on
>> >>> how
>> >>> > > to optimize that further by trading cpu for a bit more memory,
>> but not
>> >>> sure
>> >>> > >
>> >>> >
>> >>> > In my branch on this topic I used HashMap instead of array. The
>> lookup is
>> >>> > faster. Not sure how much memory overhead there is.
>> >>>
>> >>> yeah. havent had time to profile it yet. there are some memory
>> >>> efficient hashmaps floating around, maybe we can adapt one of them.
>> >>>
>> >>
>> >> I've added ComponentQueue2 based on HashMap with the same initial
>> capacity
>> >> (8) and
>> >> loadFactor 1.
>> >>
>> >> wicket-util has MicroMap for 1entry and MiniMap for fixed size entries
>> but
>> >> it doesn't use hash function so it iterates over the entries as we do
>> over
>> >> the array in ComponentQueue(1).
>> >>
>> >> With ComponentQueue2 the map will start with capacity 8 and will double
>> >> when the ninth is to be added, as in ComponentQueue. But it won't
>> shrink
>> >> until it becomes with size 0.
>> >> org.apache.wicket.queueing.ComponentQueueingPerformanceTest gives
>> almost
>> >> the same results for both impls here:
>> >> add duration: ~2500
>> >> queue duration: ~2400
>> >>
>> >> memory wise Intellij IDEA reports:
>> >> - with ComponentQueue: max memory 88Mb
>> >> - with ComponentQueue2: max memory 154Mb
>> >>
>> >> so ComponentQueue is a winner here. I've added ComponentQueue2 just in
>> case
>> >> someone wants to try to optimize it
>> >>
>> >>
>> >>>
>> >>> -igor
>> >>>
>> >>> > > if its needed since the overhead is low and because its only
>> present
>> >>> when
>> >>> > > queuing is used. also the measurements are not too accurate
>> because
>> >>> most of
>> >>> > > the time is spent initializing and tearing down a WicketTester
>> >>> instance.
>> >>> > >
>> >>> > > memory overhead is also low, two slots (one of which can/should be
>> >>> > > converted to a flag) are added to MarkupContainer.
>> >>> > >
>> >>> > > see ComponentQueuing test for some examples. i would appreciate
>> some
>> >>> help
>> >>> > > getting Border and InlineEnclosure working if someone has time.
>> >>> > >
>> >>> > > look over this and lets discuss if/when we should merge it into
>> master.
>> >>> > >
>> >>> > > -igor
>> >>>
>>
>
>

Re: Markup driven component tree

Posted by Igor Vaynberg <ig...@gmail.com>.
tests fixed, merged into master.

-igor

On Tue, Feb 18, 2014 at 5:29 AM, Martin Grigorov <mg...@apache.org> wrote:
> On Mon, Feb 17, 2014 at 5:48 AM, Igor Vaynberg <ig...@gmail.com>wrote:
>
>> i think the implementation is good enough to be merged into master
>> now. it supports:
>>
>
> I am still not able to fix the tests
> I will need more time to get acquaint with the new code to be able to
> maintain it
>
>
>>
>> * dequeuing algorithm that delegates to components so subclasses can
>> override (this is how repeaters and borders support it)
>> * support for all major constructs: panels, borders, repeaters
>> * support for auto component hierarchy - they are dequeued and queued
>> up children are placed as the children of auto components - this makes
>> things like enclosures trivial to implement where as before they were
>> fairy complex
>> * performance comparable to adding, still some room for improvement
>> with clever/efficient data structures maybe, but i dont think its
>> needed...
>>
>
> I see regression here
> last time I ran the performance test it needed 9s to run and used 88Mb
> memory
> now the time is 11s and the memory is 201Mb
>
>
>>
>> todo:
>>
>> * fragments - should be trivial, possibly as trivial as letting it
>> implement IQueueRegion
>> * check markup inheritance works on pages, panels, fragments.
>> * examples
>> * update to the guide
>>
>> -igor
>>
>>
>>
>>
>>
>> On Fri, Feb 14, 2014 at 8:36 AM, Igor Vaynberg <ig...@gmail.com>
>> wrote:
>> > i am reworking the implementation a bit to properly support borders
>> > and repeaters by delegating to components...will check it in when i
>> > have it working...
>> >
>> > -igor
>> >
>> >
>> > On Fri, Feb 14, 2014 at 7:26 AM, Martin Grigorov <mg...@apache.org>
>> wrote:
>> >> On Mon, Feb 10, 2014 at 6:01 PM, Igor Vaynberg <igor.vaynberg@gmail.com
>> >wrote:
>> >>
>> >>> On Mon, Feb 10, 2014 at 6:26 AM, Martin Grigorov <mgrigorov@apache.org
>> >
>> >>> wrote:
>> >>> >
>> >>> > On Mon, Feb 10, 2014 at 9:43 AM, Igor Vaynberg <
>> igor.vaynberg@gmail.com
>> >>> >wrote:
>> >>> >
>> >>> > > i just pushed my new idea into sandbox/component-queueing-2
>> >>> > >
>> >>> > > the way this works now is instead of doing it in onInitialize()
>> and in
>> >>> > > onConfigure() and all the other places dequeuing now works
>> >>> progressively.
>> >>> > > upon a change (container.queue() or component.add()) a dequeue
>> will be
>> >>> > > tried.
>> >>> > >
>> >>> > > it even works well with resolved components like enclosures. for
>> such
>> >>> > > components the markup of page/panel is traversed in onInitialize()
>> and
>> >>> all
>> >>> > > auto components are placed into the queue. later as components are
>> >>> > > added/queued these components will be placed into the correct
>> place in
>> >>> the
>> >>> > > hierarchy. if queue() is used children of these components will be
>> >>> placed
>> >>> > > under them in correct hierarchy place. this is a big win for using
>> >>> queueing
>> >>> > > over adding.
>> >>> > >
>> >>> > > repeaters also work. the repeater items themselves have to be
>> added to
>> >>> the
>> >>> > > repeater, but item's children can be queued. this is not a problem
>> >>> since
>> >>> > > items are mostly added by framework classes.
>> >>> > >
>> >>> > > Borders do not yet work mainly because i havent tried to make them
>> >>> work.
>> >>> > > the tricky part there is to keep the border and BorderBody queues
>> >>> separate.
>> >>> > >
>> >>> >
>> >>> > I've added some code to support it but it needs more work.
>> >>> > See my response to the commit notification email of my changes.
>> >>>
>> >>
>> >> Basic usage of Border is now supported.
>> >> I have added a test with nested Borders and it fails.
>> >> Please check
>> >>
>> org.apache.wicket.queueing.ComponentQueueingTest#dequeueWithNestedBorders
>> >>
>> >>
>> >>>  >
>> >>> > Also we have BorderBehavior and BorderPanel.
>> >>> > I think (almost) no one uses those but they exist.
>> >>>
>> >>> imho we can nuke these two things from 7. they dont look very useful.
>> >>> probably added just because we could.
>> >>>
>> >>> > > InlineEnclosures do not yet work because the code for figuring out
>> the
>> >>> > > value of the child attribute is really convoluted for the simple
>> thing
>> >>> its
>> >>> > > supposed to do and i didnt bother parsing it. Should be very
>> similar
>> >>> to how
>> >>> > > EnclosureHandler works.
>> >>> > >
>> >>> >
>> >>> > Done.
>> >>>
>> >>> thanks.
>> >>>
>> >>> > > the performance is good. there is ComponentQueueingPerformanceTest
>> >>> with a
>> >>> > > disabled test. give it a go and let me know the results. on my box
>> >>> queuing
>> >>> > > had under 10% overhead, which is acceptable. I also have some
>> ideas on
>> >>> how
>> >>> > > to optimize that further by trading cpu for a bit more memory, but
>> not
>> >>> sure
>> >>> > >
>> >>> >
>> >>> > In my branch on this topic I used HashMap instead of array. The
>> lookup is
>> >>> > faster. Not sure how much memory overhead there is.
>> >>>
>> >>> yeah. havent had time to profile it yet. there are some memory
>> >>> efficient hashmaps floating around, maybe we can adapt one of them.
>> >>>
>> >>
>> >> I've added ComponentQueue2 based on HashMap with the same initial
>> capacity
>> >> (8) and
>> >> loadFactor 1.
>> >>
>> >> wicket-util has MicroMap for 1entry and MiniMap for fixed size entries
>> but
>> >> it doesn't use hash function so it iterates over the entries as we do
>> over
>> >> the array in ComponentQueue(1).
>> >>
>> >> With ComponentQueue2 the map will start with capacity 8 and will double
>> >> when the ninth is to be added, as in ComponentQueue. But it won't shrink
>> >> until it becomes with size 0.
>> >> org.apache.wicket.queueing.ComponentQueueingPerformanceTest gives almost
>> >> the same results for both impls here:
>> >> add duration: ~2500
>> >> queue duration: ~2400
>> >>
>> >> memory wise Intellij IDEA reports:
>> >> - with ComponentQueue: max memory 88Mb
>> >> - with ComponentQueue2: max memory 154Mb
>> >>
>> >> so ComponentQueue is a winner here. I've added ComponentQueue2 just in
>> case
>> >> someone wants to try to optimize it
>> >>
>> >>
>> >>>
>> >>> -igor
>> >>>
>> >>> > > if its needed since the overhead is low and because its only
>> present
>> >>> when
>> >>> > > queuing is used. also the measurements are not too accurate because
>> >>> most of
>> >>> > > the time is spent initializing and tearing down a WicketTester
>> >>> instance.
>> >>> > >
>> >>> > > memory overhead is also low, two slots (one of which can/should be
>> >>> > > converted to a flag) are added to MarkupContainer.
>> >>> > >
>> >>> > > see ComponentQueuing test for some examples. i would appreciate
>> some
>> >>> help
>> >>> > > getting Border and InlineEnclosure working if someone has time.
>> >>> > >
>> >>> > > look over this and lets discuss if/when we should merge it into
>> master.
>> >>> > >
>> >>> > > -igor
>> >>>
>>

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
On Mon, Feb 17, 2014 at 5:48 AM, Igor Vaynberg <ig...@gmail.com>wrote:

> i think the implementation is good enough to be merged into master
> now. it supports:
>

I am still not able to fix the tests
I will need more time to get acquaint with the new code to be able to
maintain it


>
> * dequeuing algorithm that delegates to components so subclasses can
> override (this is how repeaters and borders support it)
> * support for all major constructs: panels, borders, repeaters
> * support for auto component hierarchy - they are dequeued and queued
> up children are placed as the children of auto components - this makes
> things like enclosures trivial to implement where as before they were
> fairy complex
> * performance comparable to adding, still some room for improvement
> with clever/efficient data structures maybe, but i dont think its
> needed...
>

I see regression here
last time I ran the performance test it needed 9s to run and used 88Mb
memory
now the time is 11s and the memory is 201Mb


>
> todo:
>
> * fragments - should be trivial, possibly as trivial as letting it
> implement IQueueRegion
> * check markup inheritance works on pages, panels, fragments.
> * examples
> * update to the guide
>
> -igor
>
>
>
>
>
> On Fri, Feb 14, 2014 at 8:36 AM, Igor Vaynberg <ig...@gmail.com>
> wrote:
> > i am reworking the implementation a bit to properly support borders
> > and repeaters by delegating to components...will check it in when i
> > have it working...
> >
> > -igor
> >
> >
> > On Fri, Feb 14, 2014 at 7:26 AM, Martin Grigorov <mg...@apache.org>
> wrote:
> >> On Mon, Feb 10, 2014 at 6:01 PM, Igor Vaynberg <igor.vaynberg@gmail.com
> >wrote:
> >>
> >>> On Mon, Feb 10, 2014 at 6:26 AM, Martin Grigorov <mgrigorov@apache.org
> >
> >>> wrote:
> >>> >
> >>> > On Mon, Feb 10, 2014 at 9:43 AM, Igor Vaynberg <
> igor.vaynberg@gmail.com
> >>> >wrote:
> >>> >
> >>> > > i just pushed my new idea into sandbox/component-queueing-2
> >>> > >
> >>> > > the way this works now is instead of doing it in onInitialize()
> and in
> >>> > > onConfigure() and all the other places dequeuing now works
> >>> progressively.
> >>> > > upon a change (container.queue() or component.add()) a dequeue
> will be
> >>> > > tried.
> >>> > >
> >>> > > it even works well with resolved components like enclosures. for
> such
> >>> > > components the markup of page/panel is traversed in onInitialize()
> and
> >>> all
> >>> > > auto components are placed into the queue. later as components are
> >>> > > added/queued these components will be placed into the correct
> place in
> >>> the
> >>> > > hierarchy. if queue() is used children of these components will be
> >>> placed
> >>> > > under them in correct hierarchy place. this is a big win for using
> >>> queueing
> >>> > > over adding.
> >>> > >
> >>> > > repeaters also work. the repeater items themselves have to be
> added to
> >>> the
> >>> > > repeater, but item's children can be queued. this is not a problem
> >>> since
> >>> > > items are mostly added by framework classes.
> >>> > >
> >>> > > Borders do not yet work mainly because i havent tried to make them
> >>> work.
> >>> > > the tricky part there is to keep the border and BorderBody queues
> >>> separate.
> >>> > >
> >>> >
> >>> > I've added some code to support it but it needs more work.
> >>> > See my response to the commit notification email of my changes.
> >>>
> >>
> >> Basic usage of Border is now supported.
> >> I have added a test with nested Borders and it fails.
> >> Please check
> >>
> org.apache.wicket.queueing.ComponentQueueingTest#dequeueWithNestedBorders
> >>
> >>
> >>>  >
> >>> > Also we have BorderBehavior and BorderPanel.
> >>> > I think (almost) no one uses those but they exist.
> >>>
> >>> imho we can nuke these two things from 7. they dont look very useful.
> >>> probably added just because we could.
> >>>
> >>> > > InlineEnclosures do not yet work because the code for figuring out
> the
> >>> > > value of the child attribute is really convoluted for the simple
> thing
> >>> its
> >>> > > supposed to do and i didnt bother parsing it. Should be very
> similar
> >>> to how
> >>> > > EnclosureHandler works.
> >>> > >
> >>> >
> >>> > Done.
> >>>
> >>> thanks.
> >>>
> >>> > > the performance is good. there is ComponentQueueingPerformanceTest
> >>> with a
> >>> > > disabled test. give it a go and let me know the results. on my box
> >>> queuing
> >>> > > had under 10% overhead, which is acceptable. I also have some
> ideas on
> >>> how
> >>> > > to optimize that further by trading cpu for a bit more memory, but
> not
> >>> sure
> >>> > >
> >>> >
> >>> > In my branch on this topic I used HashMap instead of array. The
> lookup is
> >>> > faster. Not sure how much memory overhead there is.
> >>>
> >>> yeah. havent had time to profile it yet. there are some memory
> >>> efficient hashmaps floating around, maybe we can adapt one of them.
> >>>
> >>
> >> I've added ComponentQueue2 based on HashMap with the same initial
> capacity
> >> (8) and
> >> loadFactor 1.
> >>
> >> wicket-util has MicroMap for 1entry and MiniMap for fixed size entries
> but
> >> it doesn't use hash function so it iterates over the entries as we do
> over
> >> the array in ComponentQueue(1).
> >>
> >> With ComponentQueue2 the map will start with capacity 8 and will double
> >> when the ninth is to be added, as in ComponentQueue. But it won't shrink
> >> until it becomes with size 0.
> >> org.apache.wicket.queueing.ComponentQueueingPerformanceTest gives almost
> >> the same results for both impls here:
> >> add duration: ~2500
> >> queue duration: ~2400
> >>
> >> memory wise Intellij IDEA reports:
> >> - with ComponentQueue: max memory 88Mb
> >> - with ComponentQueue2: max memory 154Mb
> >>
> >> so ComponentQueue is a winner here. I've added ComponentQueue2 just in
> case
> >> someone wants to try to optimize it
> >>
> >>
> >>>
> >>> -igor
> >>>
> >>> > > if its needed since the overhead is low and because its only
> present
> >>> when
> >>> > > queuing is used. also the measurements are not too accurate because
> >>> most of
> >>> > > the time is spent initializing and tearing down a WicketTester
> >>> instance.
> >>> > >
> >>> > > memory overhead is also low, two slots (one of which can/should be
> >>> > > converted to a flag) are added to MarkupContainer.
> >>> > >
> >>> > > see ComponentQueuing test for some examples. i would appreciate
> some
> >>> help
> >>> > > getting Border and InlineEnclosure working if someone has time.
> >>> > >
> >>> > > look over this and lets discuss if/when we should merge it into
> master.
> >>> > >
> >>> > > -igor
> >>>
>

Re: Markup driven component tree

Posted by Igor Vaynberg <ig...@gmail.com>.
i think the implementation is good enough to be merged into master
now. it supports:

* dequeuing algorithm that delegates to components so subclasses can
override (this is how repeaters and borders support it)
* support for all major constructs: panels, borders, repeaters
* support for auto component hierarchy - they are dequeued and queued
up children are placed as the children of auto components - this makes
things like enclosures trivial to implement where as before they were
fairy complex
* performance comparable to adding, still some room for improvement
with clever/efficient data structures maybe, but i dont think its
needed...

todo:

* fragments - should be trivial, possibly as trivial as letting it
implement IQueueRegion
* check markup inheritance works on pages, panels, fragments.
* examples
* update to the guide

-igor





On Fri, Feb 14, 2014 at 8:36 AM, Igor Vaynberg <ig...@gmail.com> wrote:
> i am reworking the implementation a bit to properly support borders
> and repeaters by delegating to components...will check it in when i
> have it working...
>
> -igor
>
>
> On Fri, Feb 14, 2014 at 7:26 AM, Martin Grigorov <mg...@apache.org> wrote:
>> On Mon, Feb 10, 2014 at 6:01 PM, Igor Vaynberg <ig...@gmail.com>wrote:
>>
>>> On Mon, Feb 10, 2014 at 6:26 AM, Martin Grigorov <mg...@apache.org>
>>> wrote:
>>> >
>>> > On Mon, Feb 10, 2014 at 9:43 AM, Igor Vaynberg <igor.vaynberg@gmail.com
>>> >wrote:
>>> >
>>> > > i just pushed my new idea into sandbox/component-queueing-2
>>> > >
>>> > > the way this works now is instead of doing it in onInitialize() and in
>>> > > onConfigure() and all the other places dequeuing now works
>>> progressively.
>>> > > upon a change (container.queue() or component.add()) a dequeue will be
>>> > > tried.
>>> > >
>>> > > it even works well with resolved components like enclosures. for such
>>> > > components the markup of page/panel is traversed in onInitialize() and
>>> all
>>> > > auto components are placed into the queue. later as components are
>>> > > added/queued these components will be placed into the correct place in
>>> the
>>> > > hierarchy. if queue() is used children of these components will be
>>> placed
>>> > > under them in correct hierarchy place. this is a big win for using
>>> queueing
>>> > > over adding.
>>> > >
>>> > > repeaters also work. the repeater items themselves have to be added to
>>> the
>>> > > repeater, but item's children can be queued. this is not a problem
>>> since
>>> > > items are mostly added by framework classes.
>>> > >
>>> > > Borders do not yet work mainly because i havent tried to make them
>>> work.
>>> > > the tricky part there is to keep the border and BorderBody queues
>>> separate.
>>> > >
>>> >
>>> > I've added some code to support it but it needs more work.
>>> > See my response to the commit notification email of my changes.
>>>
>>
>> Basic usage of Border is now supported.
>> I have added a test with nested Borders and it fails.
>> Please check
>> org.apache.wicket.queueing.ComponentQueueingTest#dequeueWithNestedBorders
>>
>>
>>>  >
>>> > Also we have BorderBehavior and BorderPanel.
>>> > I think (almost) no one uses those but they exist.
>>>
>>> imho we can nuke these two things from 7. they dont look very useful.
>>> probably added just because we could.
>>>
>>> > > InlineEnclosures do not yet work because the code for figuring out the
>>> > > value of the child attribute is really convoluted for the simple thing
>>> its
>>> > > supposed to do and i didnt bother parsing it. Should be very similar
>>> to how
>>> > > EnclosureHandler works.
>>> > >
>>> >
>>> > Done.
>>>
>>> thanks.
>>>
>>> > > the performance is good. there is ComponentQueueingPerformanceTest
>>> with a
>>> > > disabled test. give it a go and let me know the results. on my box
>>> queuing
>>> > > had under 10% overhead, which is acceptable. I also have some ideas on
>>> how
>>> > > to optimize that further by trading cpu for a bit more memory, but not
>>> sure
>>> > >
>>> >
>>> > In my branch on this topic I used HashMap instead of array. The lookup is
>>> > faster. Not sure how much memory overhead there is.
>>>
>>> yeah. havent had time to profile it yet. there are some memory
>>> efficient hashmaps floating around, maybe we can adapt one of them.
>>>
>>
>> I've added ComponentQueue2 based on HashMap with the same initial capacity
>> (8) and
>> loadFactor 1.
>>
>> wicket-util has MicroMap for 1entry and MiniMap for fixed size entries but
>> it doesn't use hash function so it iterates over the entries as we do over
>> the array in ComponentQueue(1).
>>
>> With ComponentQueue2 the map will start with capacity 8 and will double
>> when the ninth is to be added, as in ComponentQueue. But it won't shrink
>> until it becomes with size 0.
>> org.apache.wicket.queueing.ComponentQueueingPerformanceTest gives almost
>> the same results for both impls here:
>> add duration: ~2500
>> queue duration: ~2400
>>
>> memory wise Intellij IDEA reports:
>> - with ComponentQueue: max memory 88Mb
>> - with ComponentQueue2: max memory 154Mb
>>
>> so ComponentQueue is a winner here. I've added ComponentQueue2 just in case
>> someone wants to try to optimize it
>>
>>
>>>
>>> -igor
>>>
>>> > > if its needed since the overhead is low and because its only present
>>> when
>>> > > queuing is used. also the measurements are not too accurate because
>>> most of
>>> > > the time is spent initializing and tearing down a WicketTester
>>> instance.
>>> > >
>>> > > memory overhead is also low, two slots (one of which can/should be
>>> > > converted to a flag) are added to MarkupContainer.
>>> > >
>>> > > see ComponentQueuing test for some examples. i would appreciate some
>>> help
>>> > > getting Border and InlineEnclosure working if someone has time.
>>> > >
>>> > > look over this and lets discuss if/when we should merge it into master.
>>> > >
>>> > > -igor
>>>

Re: Markup driven component tree

Posted by Igor Vaynberg <ig...@gmail.com>.
i am reworking the implementation a bit to properly support borders
and repeaters by delegating to components...will check it in when i
have it working...

-igor


On Fri, Feb 14, 2014 at 7:26 AM, Martin Grigorov <mg...@apache.org> wrote:
> On Mon, Feb 10, 2014 at 6:01 PM, Igor Vaynberg <ig...@gmail.com>wrote:
>
>> On Mon, Feb 10, 2014 at 6:26 AM, Martin Grigorov <mg...@apache.org>
>> wrote:
>> >
>> > On Mon, Feb 10, 2014 at 9:43 AM, Igor Vaynberg <igor.vaynberg@gmail.com
>> >wrote:
>> >
>> > > i just pushed my new idea into sandbox/component-queueing-2
>> > >
>> > > the way this works now is instead of doing it in onInitialize() and in
>> > > onConfigure() and all the other places dequeuing now works
>> progressively.
>> > > upon a change (container.queue() or component.add()) a dequeue will be
>> > > tried.
>> > >
>> > > it even works well with resolved components like enclosures. for such
>> > > components the markup of page/panel is traversed in onInitialize() and
>> all
>> > > auto components are placed into the queue. later as components are
>> > > added/queued these components will be placed into the correct place in
>> the
>> > > hierarchy. if queue() is used children of these components will be
>> placed
>> > > under them in correct hierarchy place. this is a big win for using
>> queueing
>> > > over adding.
>> > >
>> > > repeaters also work. the repeater items themselves have to be added to
>> the
>> > > repeater, but item's children can be queued. this is not a problem
>> since
>> > > items are mostly added by framework classes.
>> > >
>> > > Borders do not yet work mainly because i havent tried to make them
>> work.
>> > > the tricky part there is to keep the border and BorderBody queues
>> separate.
>> > >
>> >
>> > I've added some code to support it but it needs more work.
>> > See my response to the commit notification email of my changes.
>>
>
> Basic usage of Border is now supported.
> I have added a test with nested Borders and it fails.
> Please check
> org.apache.wicket.queueing.ComponentQueueingTest#dequeueWithNestedBorders
>
>
>>  >
>> > Also we have BorderBehavior and BorderPanel.
>> > I think (almost) no one uses those but they exist.
>>
>> imho we can nuke these two things from 7. they dont look very useful.
>> probably added just because we could.
>>
>> > > InlineEnclosures do not yet work because the code for figuring out the
>> > > value of the child attribute is really convoluted for the simple thing
>> its
>> > > supposed to do and i didnt bother parsing it. Should be very similar
>> to how
>> > > EnclosureHandler works.
>> > >
>> >
>> > Done.
>>
>> thanks.
>>
>> > > the performance is good. there is ComponentQueueingPerformanceTest
>> with a
>> > > disabled test. give it a go and let me know the results. on my box
>> queuing
>> > > had under 10% overhead, which is acceptable. I also have some ideas on
>> how
>> > > to optimize that further by trading cpu for a bit more memory, but not
>> sure
>> > >
>> >
>> > In my branch on this topic I used HashMap instead of array. The lookup is
>> > faster. Not sure how much memory overhead there is.
>>
>> yeah. havent had time to profile it yet. there are some memory
>> efficient hashmaps floating around, maybe we can adapt one of them.
>>
>
> I've added ComponentQueue2 based on HashMap with the same initial capacity
> (8) and
> loadFactor 1.
>
> wicket-util has MicroMap for 1entry and MiniMap for fixed size entries but
> it doesn't use hash function so it iterates over the entries as we do over
> the array in ComponentQueue(1).
>
> With ComponentQueue2 the map will start with capacity 8 and will double
> when the ninth is to be added, as in ComponentQueue. But it won't shrink
> until it becomes with size 0.
> org.apache.wicket.queueing.ComponentQueueingPerformanceTest gives almost
> the same results for both impls here:
> add duration: ~2500
> queue duration: ~2400
>
> memory wise Intellij IDEA reports:
> - with ComponentQueue: max memory 88Mb
> - with ComponentQueue2: max memory 154Mb
>
> so ComponentQueue is a winner here. I've added ComponentQueue2 just in case
> someone wants to try to optimize it
>
>
>>
>> -igor
>>
>> > > if its needed since the overhead is low and because its only present
>> when
>> > > queuing is used. also the measurements are not too accurate because
>> most of
>> > > the time is spent initializing and tearing down a WicketTester
>> instance.
>> > >
>> > > memory overhead is also low, two slots (one of which can/should be
>> > > converted to a flag) are added to MarkupContainer.
>> > >
>> > > see ComponentQueuing test for some examples. i would appreciate some
>> help
>> > > getting Border and InlineEnclosure working if someone has time.
>> > >
>> > > look over this and lets discuss if/when we should merge it into master.
>> > >
>> > > -igor
>>

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
On Mon, Feb 10, 2014 at 6:01 PM, Igor Vaynberg <ig...@gmail.com>wrote:

> On Mon, Feb 10, 2014 at 6:26 AM, Martin Grigorov <mg...@apache.org>
> wrote:
> >
> > On Mon, Feb 10, 2014 at 9:43 AM, Igor Vaynberg <igor.vaynberg@gmail.com
> >wrote:
> >
> > > i just pushed my new idea into sandbox/component-queueing-2
> > >
> > > the way this works now is instead of doing it in onInitialize() and in
> > > onConfigure() and all the other places dequeuing now works
> progressively.
> > > upon a change (container.queue() or component.add()) a dequeue will be
> > > tried.
> > >
> > > it even works well with resolved components like enclosures. for such
> > > components the markup of page/panel is traversed in onInitialize() and
> all
> > > auto components are placed into the queue. later as components are
> > > added/queued these components will be placed into the correct place in
> the
> > > hierarchy. if queue() is used children of these components will be
> placed
> > > under them in correct hierarchy place. this is a big win for using
> queueing
> > > over adding.
> > >
> > > repeaters also work. the repeater items themselves have to be added to
> the
> > > repeater, but item's children can be queued. this is not a problem
> since
> > > items are mostly added by framework classes.
> > >
> > > Borders do not yet work mainly because i havent tried to make them
> work.
> > > the tricky part there is to keep the border and BorderBody queues
> separate.
> > >
> >
> > I've added some code to support it but it needs more work.
> > See my response to the commit notification email of my changes.
>

Basic usage of Border is now supported.
I have added a test with nested Borders and it fails.
Please check
org.apache.wicket.queueing.ComponentQueueingTest#dequeueWithNestedBorders


>  >
> > Also we have BorderBehavior and BorderPanel.
> > I think (almost) no one uses those but they exist.
>
> imho we can nuke these two things from 7. they dont look very useful.
> probably added just because we could.
>
> > > InlineEnclosures do not yet work because the code for figuring out the
> > > value of the child attribute is really convoluted for the simple thing
> its
> > > supposed to do and i didnt bother parsing it. Should be very similar
> to how
> > > EnclosureHandler works.
> > >
> >
> > Done.
>
> thanks.
>
> > > the performance is good. there is ComponentQueueingPerformanceTest
> with a
> > > disabled test. give it a go and let me know the results. on my box
> queuing
> > > had under 10% overhead, which is acceptable. I also have some ideas on
> how
> > > to optimize that further by trading cpu for a bit more memory, but not
> sure
> > >
> >
> > In my branch on this topic I used HashMap instead of array. The lookup is
> > faster. Not sure how much memory overhead there is.
>
> yeah. havent had time to profile it yet. there are some memory
> efficient hashmaps floating around, maybe we can adapt one of them.
>

I've added ComponentQueue2 based on HashMap with the same initial capacity
(8) and
loadFactor 1.

wicket-util has MicroMap for 1entry and MiniMap for fixed size entries but
it doesn't use hash function so it iterates over the entries as we do over
the array in ComponentQueue(1).

With ComponentQueue2 the map will start with capacity 8 and will double
when the ninth is to be added, as in ComponentQueue. But it won't shrink
until it becomes with size 0.
org.apache.wicket.queueing.ComponentQueueingPerformanceTest gives almost
the same results for both impls here:
add duration: ~2500
queue duration: ~2400

memory wise Intellij IDEA reports:
- with ComponentQueue: max memory 88Mb
- with ComponentQueue2: max memory 154Mb

so ComponentQueue is a winner here. I've added ComponentQueue2 just in case
someone wants to try to optimize it


>
> -igor
>
> > > if its needed since the overhead is low and because its only present
> when
> > > queuing is used. also the measurements are not too accurate because
> most of
> > > the time is spent initializing and tearing down a WicketTester
> instance.
> > >
> > > memory overhead is also low, two slots (one of which can/should be
> > > converted to a flag) are added to MarkupContainer.
> > >
> > > see ComponentQueuing test for some examples. i would appreciate some
> help
> > > getting Border and InlineEnclosure working if someone has time.
> > >
> > > look over this and lets discuss if/when we should merge it into master.
> > >
> > > -igor
>

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
On Mon, Feb 10, 2014 at 6:01 PM, Igor Vaynberg <ig...@gmail.com>wrote:

> On Mon, Feb 10, 2014 at 6:26 AM, Martin Grigorov <mg...@apache.org>
> wrote:
> >
> > On Mon, Feb 10, 2014 at 9:43 AM, Igor Vaynberg <igor.vaynberg@gmail.com
> >wrote:
> >
> > > i just pushed my new idea into sandbox/component-queueing-2
> > >
> > > the way this works now is instead of doing it in onInitialize() and in
> > > onConfigure() and all the other places dequeuing now works
> progressively.
> > > upon a change (container.queue() or component.add()) a dequeue will be
> > > tried.
> > >
> > > it even works well with resolved components like enclosures. for such
> > > components the markup of page/panel is traversed in onInitialize() and
> all
> > > auto components are placed into the queue. later as components are
> > > added/queued these components will be placed into the correct place in
> the
> > > hierarchy. if queue() is used children of these components will be
> placed
> > > under them in correct hierarchy place. this is a big win for using
> queueing
> > > over adding.
> > >
> > > repeaters also work. the repeater items themselves have to be added to
> the
> > > repeater, but item's children can be queued. this is not a problem
> since
> > > items are mostly added by framework classes.
> > >
> > > Borders do not yet work mainly because i havent tried to make them
> work.
> > > the tricky part there is to keep the border and BorderBody queues
> separate.
> > >
> >
> > I've added some code to support it but it needs more work.
> > See my response to the commit notification email of my changes.
> >
> > Also we have BorderBehavior and BorderPanel.
> > I think (almost) no one uses those but they exist.
>
> imho we can nuke these two things from 7. they dont look very useful.
> probably added just because we could.
>

I find BorderBehavior as a nice demo - it shows how to have a behavior with
its own markup
It is actually very old. Its previous name is MarkupComponentBorder.
My assumption that it is not used is because I don't remember anyone
talking about it - neither bug reports, nor questions for clarifications in
users@.
Its only usage in Wicket code
is org.apache.wicket.examples.forminput.BeforeAndAfterBorder, so I suggest
to move it to wicket-examples instead of totally nuke it.

BorderPanel is since 1.5.
Juergen introduced it to show how to use a Panel instead of a Border when
there was a discussion whether to remove 'final' from MarkupContainer's
add/remove/replace/addOrReplace methods because Border needed to delegate
all of them, not just add()
Since then I don't remember anyone talking about it

>
> > > InlineEnclosures do not yet work because the code for figuring out the
> > > value of the child attribute is really convoluted for the simple thing
> its
> > > supposed to do and i didnt bother parsing it. Should be very similar
> to how
> > > EnclosureHandler works.
> > >
> >
> > Done.
>
> thanks.
>
> > > the performance is good. there is ComponentQueueingPerformanceTest
> with a
> > > disabled test. give it a go and let me know the results. on my box
> queuing
> > > had under 10% overhead, which is acceptable. I also have some ideas on
> how
> > > to optimize that further by trading cpu for a bit more memory, but not
> sure
> > >
> >
> > In my branch on this topic I used HashMap instead of array. The lookup is
> > faster. Not sure how much memory overhead there is.
>
> yeah. havent had time to profile it yet. there are some memory
> efficient hashmaps floating around, maybe we can adapt one of them.
>
> -igor
>
> > > if its needed since the overhead is low and because its only present
> when
> > > queuing is used. also the measurements are not too accurate because
> most of
> > > the time is spent initializing and tearing down a WicketTester
> instance.
> > >
> > > memory overhead is also low, two slots (one of which can/should be
> > > converted to a flag) are added to MarkupContainer.
> > >
> > > see ComponentQueuing test for some examples. i would appreciate some
> help
> > > getting Border and InlineEnclosure working if someone has time.
> > >
> > > look over this and lets discuss if/when we should merge it into master.
> > >
> > > -igor
>

Re: Markup driven component tree

Posted by Igor Vaynberg <ig...@gmail.com>.
On Mon, Feb 10, 2014 at 6:26 AM, Martin Grigorov <mg...@apache.org> wrote:
>
> On Mon, Feb 10, 2014 at 9:43 AM, Igor Vaynberg <ig...@gmail.com>wrote:
>
> > i just pushed my new idea into sandbox/component-queueing-2
> >
> > the way this works now is instead of doing it in onInitialize() and in
> > onConfigure() and all the other places dequeuing now works progressively.
> > upon a change (container.queue() or component.add()) a dequeue will be
> > tried.
> >
> > it even works well with resolved components like enclosures. for such
> > components the markup of page/panel is traversed in onInitialize() and all
> > auto components are placed into the queue. later as components are
> > added/queued these components will be placed into the correct place in the
> > hierarchy. if queue() is used children of these components will be placed
> > under them in correct hierarchy place. this is a big win for using queueing
> > over adding.
> >
> > repeaters also work. the repeater items themselves have to be added to the
> > repeater, but item's children can be queued. this is not a problem since
> > items are mostly added by framework classes.
> >
> > Borders do not yet work mainly because i havent tried to make them work.
> > the tricky part there is to keep the border and BorderBody queues separate.
> >
>
> I've added some code to support it but it needs more work.
> See my response to the commit notification email of my changes.
>
> Also we have BorderBehavior and BorderPanel.
> I think (almost) no one uses those but they exist.

imho we can nuke these two things from 7. they dont look very useful.
probably added just because we could.

> > InlineEnclosures do not yet work because the code for figuring out the
> > value of the child attribute is really convoluted for the simple thing its
> > supposed to do and i didnt bother parsing it. Should be very similar to how
> > EnclosureHandler works.
> >
>
> Done.

thanks.

> > the performance is good. there is ComponentQueueingPerformanceTest with a
> > disabled test. give it a go and let me know the results. on my box queuing
> > had under 10% overhead, which is acceptable. I also have some ideas on how
> > to optimize that further by trading cpu for a bit more memory, but not sure
> >
>
> In my branch on this topic I used HashMap instead of array. The lookup is
> faster. Not sure how much memory overhead there is.

yeah. havent had time to profile it yet. there are some memory
efficient hashmaps floating around, maybe we can adapt one of them.

-igor

> > if its needed since the overhead is low and because its only present when
> > queuing is used. also the measurements are not too accurate because most of
> > the time is spent initializing and tearing down a WicketTester instance.
> >
> > memory overhead is also low, two slots (one of which can/should be
> > converted to a flag) are added to MarkupContainer.
> >
> > see ComponentQueuing test for some examples. i would appreciate some help
> > getting Border and InlineEnclosure working if someone has time.
> >
> > look over this and lets discuss if/when we should merge it into master.
> >
> > -igor

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
On Mon, Feb 10, 2014 at 9:43 AM, Igor Vaynberg <ig...@gmail.com>wrote:

> i just pushed my new idea into sandbox/component-queueing-2
>
> the way this works now is instead of doing it in onInitialize() and in
> onConfigure() and all the other places dequeuing now works progressively.
> upon a change (container.queue() or component.add()) a dequeue will be
> tried.
>
> it even works well with resolved components like enclosures. for such
> components the markup of page/panel is traversed in onInitialize() and all
> auto components are placed into the queue. later as components are
> added/queued these components will be placed into the correct place in the
> hierarchy. if queue() is used children of these components will be placed
> under them in correct hierarchy place. this is a big win for using queueing
> over adding.
>
> repeaters also work. the repeater items themselves have to be added to the
> repeater, but item's children can be queued. this is not a problem since
> items are mostly added by framework classes.
>
> Borders do not yet work mainly because i havent tried to make them work.
> the tricky part there is to keep the border and BorderBody queues separate.
>

I've added some code to support it but it needs more work.
See my response to the commit notification email of my changes.

Also we have BorderBehavior and BorderPanel.
I think (almost) no one uses those but they exist.


>
> InlineEnclosures do not yet work because the code for figuring out the
> value of the child attribute is really convoluted for the simple thing its
> supposed to do and i didnt bother parsing it. Should be very similar to how
> EnclosureHandler works.
>

Done.


>
> the performance is good. there is ComponentQueueingPerformanceTest with a
> disabled test. give it a go and let me know the results. on my box queuing
> had under 10% overhead, which is acceptable. I also have some ideas on how
> to optimize that further by trading cpu for a bit more memory, but not sure
>

In my branch on this topic I used HashMap instead of array. The lookup is
faster. Not sure how much memory overhead there is.


> if its needed since the overhead is low and because its only present when
> queuing is used. also the measurements are not too accurate because most of
> the time is spent initializing and tearing down a WicketTester instance.
>
> memory overhead is also low, two slots (one of which can/should be
> converted to a flag) are added to MarkupContainer.
>
> see ComponentQueuing test for some examples. i would appreciate some help
> getting Border and InlineEnclosure working if someone has time.
>
> look over this and lets discuss if/when we should merge it into master.
>
> -igor
>
>
>
> On Fri, Jan 31, 2014 at 1:17 AM, Martin Grigorov <mgrigorov@apache.org
> >wrote:
>
> > Hi Sven,
> >
> > The component tree rebuilding adds CPU time :-|
> > I guess most of the applications would still prefer the current approach
> > with the manual construction of the tree in Java land.
> >
> > Even worse - the rebuilding is needed few times:
> > - once before calling Page#onInitialize() so all enqueued children in the
> > constructors will have their correct parent and thus their
> #onInitialize()
> > will be called too
> > - after Page#onInitialize() because the application may enqueue more
> > children in any Component#onInitialize()
> > - finally during rendering because a component may get enqueued in
> > #onConfigure
> >
> > Component tree re-arranging is something important too. I have listed it
> as
> > task #2 in my first mail in this thread.
> > At the moment the children of an enclosure appear at their correct
> position
> > only with when they are enqueued. More work is needed to support when
> they
> > are added (as in any existing application at the moment).
> >
> > I'm wondering what idea Igor has. We need to fix the Eclipse settings
> state
> > soon.
> >
> > On Thu, Jan 30, 2014 at 6:36 PM, Sven Meier <sv...@meiers.net> wrote:
> >
> > > Hi Martin,
> > >
> > > if we want markup driven component trees in Wicket, we have to decide
> > > whether this is optional or always supported.
> > >
> > > Currently it's a mix of both: a developer might enqueue components, but
> > > they are not used because no listener or behavior rebuilds the
> container.
> > >
> > > As it is now, we could equally well make it explicit, i.e. move
> > everything
> > > into a temporary behavior, that keeps the enqueued components until it
> is
> > > able to rebuild the container:
> > >
> > >         RebuildBehavior#rebuild(Component... cs);
> > >
> > >         ComponentA a = new ComponentA("a");
> > >         ComponentB b = new ComponentB("b");
> > >         ComponentC c = new ComponentC("c");
> > >         add(rebuild(a, b, c));
> > >
> > > What I dislike about an optional solution though: It doesn't solve our
> > > issues with non-auto components inside of enclosures. I would prefer a
> > > solution which takes care of these too, i.e. it would be able to
> > re-arrange
> > > already added components.
> > >
> > >
> > > Regards
> > > Sven
> > >
> > >
> > > On 01/27/2014 02:14 PM, Martin Grigorov wrote:
> > >
> > >> I am suspending my work on this because I think there is not enough
> > >> interest in this feature at the moment.
> > >>
> > >> Martin Grigorov
> > >> Wicket Training and Consulting
> > >>
> > >>
> > >> On Mon, Jan 27, 2014 at 10:07 AM, Martin Grigorov <
> mgrigorov@apache.org
> > >> >wrote:
> > >>
> > >>  Reading the archives for Igor's work on "component queueing" I see
> > >>>
> > >>> Igor Vaynberg<https://issues.apache.org/jira/secure/
> > >>> ViewProfile.jspa?name=ivaynberg> added
> > >>>
> > >>> a comment - 09/Jul/11 23:39
> > >>>
> > >>> @Juergen, right now your tests only test for rendering, but they
> should
> > >>> also test that before queued component's oninitialize is called the
> > >>> component is already a child of the correct parent.
> > >>>
> > >>>   https://issues.apache.org/jira/browse/WICKET-3335
> > >>>
> > >>>
> > >>> This means that
> > >>> org.apache.wicket.application.IComponentInitializationListener cannot
> > be
> > >>> used. The tree (re)building should happen *before *components'
> > >>>
> > >>> #onInitialize() and .IComponentInitializationListener#onInitialize()
> is
> > >>> called *after*.
> > >>>
> > >>> Martin Grigorov
> > >>> Wicket Training and Consulting
> > >>>
> > >>>
> > >>> On Fri, Jan 24, 2014 at 2:22 PM, Martin Grigorov <
> mgrigorov@apache.org
> > >>> >wrote:
> > >>>
> > >>>  I've added alternative ways to use MarkupDrivenComponentTreeBuilder:
> > >>>> - with org.apache.wicket.MarkupDrivenTreeInitializionListener
> > >>>> - with
> org.apache.wicket.MarkupDrivenComponentTreeBehavior#onConfigure
> > >>>>
> > >>>> Both of them do not check the configuration setting whether markup
> > >>>> driven
> > >>>> tree construction is enabled for now.
> > >>>>
> > >>>> The approach with MarkupDrivenTreeInitializionListener works the
> same
> > >>>> way
> > >>>> as the "inlined" version. The component tree rebuild is activated
> > >>>> *after*
> > >>>> all Component#onInitialize().
> > >>>>
> > >>>> The approach with MarkupDrivenComponentTreeBehavior uses
> > >>>> #onConfigure().
> > >>>> Here I had to change Enclosure class - the child component resolving
> > >>>> should
> > >>>> be done as late as possible just before the rendering phase starts.
> > >>>>
> > >>>> Martin Grigorov
> > >>>> Wicket Training and Consulting
> > >>>>
> > >>>>
> > >>>> On Fri, Jan 24, 2014 at 11:47 AM, Martin Grigorov <
> > mgrigorov@apache.org
> > >>>> >wrote:
> > >>>>
> > >>>>  OK, the new impl is committed.
> > >>>>> Now MarkupContainer has #enqueue(Component...) method that adds
> > >>>>> components into a list.
> > >>>>> Later org.apache.wicket.ComponentTreeBuilder#rebuild() uses the
> list,
> > >>>>> and finally the list is null-yfied in #onDetach() so it is not
> > >>>>> serialized
> > >>>>> and not available for the next requests. I guess the null-yfing can
> > be
> > >>>>> done
> > >>>>> earlier so even the first request have the extra bytes after the
> > >>>>> rebuild of
> > >>>>> the tree.
> > >>>>>
> > >>>>> No need of @Auto anymore.
> > >>>>>
> > >>>>> Martin Grigorov
> > >>>>> Wicket Training and Consulting
> > >>>>>
> > >>>>>
> > >>>>> On Fri, Jan 24, 2014 at 10:39 AM, Martin Grigorov <
> > >>>>> mgrigorov@apache.org>wrote:
> > >>>>>
> > >>>>>
> > >>>>>> On Fri, Jan 24, 2014 at 9:48 AM, Sven Meier <sv...@meiers.net>
> > wrote:
> > >>>>>>
> > >>>>>>  per-component basis - yes, as I explained earlier this is
> possible
> > >>>>>>>>
> > >>>>>>> with the current impl
> > >>>>>>>
> > >>>>>>> I must have missed that. Is there an example in the branch?
> > >>>>>>>
> > >>>>>>>  See
> > >>>>>> https://github.com/apache/wicket/blob/markup-driven-
> > >>>>>> component-tree/wicket-core/src/main/java/org/apache/
> > >>>>>> wicket/MarkupContainer.java?source=c#L1886
> > >>>>>> There is no test yet.
> > >>>>>>
> > >>>>>>
> > >>>>>>  I don't understand why there's need for an @Auto annotation. Why
> > >>>>>>> would
> > >>>>>>> some components be annotated and some not?
> > >>>>>>>
> > >>>>>>
> > >>>>>> The annotation was needed to be able to find the component faster.
> > >>>>>> I.e. check only annotated fields. If @Auto(id=...) then use the id
> > to
> > >>>>>> match against the component tag id.
> > >>>>>>
> > >>>>>> But with my new idea, the one that will solve the issue with the
> > extra
> > >>>>>> bytes, this won't be needed anymore.
> > >>>>>> Stay tuned.
> > >>>>>>
> > >>>>>>
> > >>>>>>
> > >>>>>>>   behaviors don't have hooks for onInitialize()
> > >>>>>>> It could be done in #onConfigue(), that's early enough.
> > >>>>>>>
> > >>>>>>
> > >>>>>> The problem is that it is called for each request.
> > >>>>>> For now I think there is no need to rebuild the component tree for
> > >>>>>> each
> > >>>>>> request, so we will have to use a guard (e.g. boolean field in the
> > >>>>>> component).
> > >>>>>> I will consider it.
> > >>>>>>
> > >>>>>>
> > >>>>>>
> > >>>>>>>   Additionally I think using Behavior will add a bit more bytes
> to
> > >>>>>>> each
> > >>>>>>>
> > >>>>>>>> component than the current solution
> > >>>>>>>>
> > >>>>>>>>  I don't think that is a problem: IMHO it's important to make
> this
> > >>>>>>> feature optional, so when users don't use it then they do not
> pay a
> > >>>>>>> price.
> > >>>>>>>
> > >>>>>>> Regards
> > >>>>>>> Sven
> > >>>>>>>
> > >>>>>>>
> > >>>>>>>
> > >>>>>>>
> > >>>>>>> On 01/24/2014 06:35 AM, Martin Grigorov wrote:
> > >>>>>>>
> > >>>>>>>  On Fri, Jan 24, 2014 at 12:04 AM, Sven Meier <sv...@meiers.net>
> > >>>>>>>> wrote:
> > >>>>>>>>
> > >>>>>>>>   Hi,
> > >>>>>>>>
> > >>>>>>>>> I don't think we're heading the right direction with this and I
> > >>>>>>>>> wouldn't
> > >>>>>>>>> advertise it as anything yet.
> > >>>>>>>>>
> > >>>>>>>>>   I'd like to advertise it anyhow now just to have more people
> > >>>>>>>>>
> > >>>>>>>> feeding me
> > >>>>>>>> with stoppers, as you and Igor do. Thanks! :-)
> > >>>>>>>>
> > >>>>>>>>
> > >>>>>>>>   There are more questions to come but here is one upfront:
> > >>>>>>>>
> > >>>>>>>>>
> > >>>>>>>>>   And it is configurable, by default disabled.
> > >>>>>>>>> As Igor has written, this does not work with component
> libraries
> > >>>>>>>>> which
> > >>>>>>>>> depend on the new feature.
> > >>>>>>>>> Couldn't this feature be enabled/disabled on a per-component
> > basis?
> > >>>>>>>>> Why
> > >>>>>>>>> not make it a behavior that you can attach to components if you
> > >>>>>>>>> want
> > >>>>>>>>> to use
> > >>>>>>>>> automatic resolving/rearranging of its children?
> > >>>>>>>>>
> > >>>>>>>>>   - per-component basis - yes, as I explained earlier this is
> > >>>>>>>>>
> > >>>>>>>> possible with
> > >>>>>>>> the current impl
> > >>>>>>>> - behaviors don't have hooks for onInitialize()
> > >>>>>>>> After Igor's feedback I think onAfterInitialize() is what is
> > needed,
> > >>>>>>>> so
> > >>>>>>>> apps can use onInitialize() as a complement to the constructor
> > >>>>>>>> Additionally I think using Behavior will add a bit more bytes to
> > >>>>>>>> each
> > >>>>>>>> component than the current solution
> > >>>>>>>>
> > >>>>>>>>
> > >>>>>>>>   Regards
> > >>>>>>>>
> > >>>>>>>>> Sven
> > >>>>>>>>>
> > >>>>>>>>>
> > >>>>>>>>>
> > >>>>>>>>> On 01/23/2014 05:20 PM, Martin Grigorov wrote:
> > >>>>>>>>>
> > >>>>>>>>>   Once the markup driven construction is done (just before
> > >>>>>>>>>
> > >>>>>>>>>> onInitialize())
> > >>>>>>>>>> the application will have to use the old good
> > >>>>>>>>>> add()/addOrReplace().
> > >>>>>>>>>>
> > >>>>>>>>>> The components are already in the MarkupContainer#children
> data
> > >>>>>>>>>> structure.
> > >>>>>>>>>> So each field will add extra 8 bytes on 64bit machine (or 4
> > bytes
> > >>>>>>>>>> with
> > >>>>>>>>>> CompressedOops enabled).
> > >>>>>>>>>> Serialization is the same - the object is written once, with
> > >>>>>>>>>> several
> > >>>>>>>>>> pointers.
> > >>>>>>>>>>
> > >>>>>>>>>> I am also not fully sure in the approach but I am
> experimenting
> > >>>>>>>>>> and
> > >>>>>>>>>> so far
> > >>>>>>>>>> it works well.
> > >>>>>>>>>> And it is configurable, by default disabled.
> > >>>>>>>>>> We can advertise it as experimental ?!
> > >>>>>>>>>>
> > >>>>>>>>>> I will add more use cases/tests soon.
> > >>>>>>>>>> And caching for the reflection stuff.
> > >>>>>>>>>>
> > >>>>>>>>>>
> > >>>>>>>>>> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <
> > >>>>>>>>>> igor.vaynberg@gmail.com>
> > >>>>>>>>>> wrote:
> > >>>>>>>>>>
> > >>>>>>>>>>    what about components added in onInitialize() or on
> > >>>>>>>>>> onConfigure()?
> > >>>>>>>>>>
> > >>>>>>>>>>  this will also lead to a higher memory/serialization space
> > usage
> > >>>>>>>>>>> since
> > >>>>>>>>>>> by default you need a field to store the component ref.
> > >>>>>>>>>>>
> > >>>>>>>>>>> not sure its worth doing it this way...
> > >>>>>>>>>>>
> > >>>>>>>>>>> -igor
> > >>>>>>>>>>>
> > >>>>>>>>>>>
> > >>>>>>>>>>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <
> > >>>>>>>>>>> mgrigorov@apache.org>
> > >>>>>>>>>>> wrote:
> > >>>>>>>>>>>
> > >>>>>>>>>>>   Hi,
> > >>>>>>>>>>>
> > >>>>>>>>>>>> Recently Fridolin Jackstadt shared his approach to
> "autowire"
> > >>>>>>>>>>>> components
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>   -
> > >>>>>>>>>>>>
> > >>>>>>>>>>>   https://github.com/wicket-acc/wicket-autowire.
> > >>>>>>>>>>>
> > >>>>>>>>>>>> I believe this approach can solve two issues:
> > >>>>>>>>>>>> - duplicate construction of the component tree - once in the
> > >>>>>>>>>>>> markup and
> > >>>>>>>>>>>> second time in Java code
> > >>>>>>>>>>>> - auto components available only in the render phase
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> Here is how I see it:
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> Any MarkupContainer that wants to use markup-driven-tree
> must
> > >>>>>>>>>>>> declare
> > >>>>>>>>>>>> the
> > >>>>>>>>>>>> components as member fields:
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> private SomeComponent aComponent;
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> These fields will be instantiated like any other component
> in
> > >>>>>>>>>>>> Wicket:
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> aComponent = new SomeComponent(id, ...);
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> The new thing is that they *won't* be added to a parent
> > >>>>>>>>>>>> component
> > >>>>>>>>>>>> explicitly/manually.
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> On Page#onInitialize() the first thing to do it to walk over
> > the
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>   component
> > >>>>>>>>>>>>
> > >>>>>>>>>>>   tree from the page's markup (just like the walk in the
> > >>>>>>>>>>> rendering
> > >>>>>>>>>>>
> > >>>>>>>>>>>> related
> > >>>>>>>>>>>> code) and resolve the missing bits.
> > >>>>>>>>>>>> I.e. while walking thru the markup tree we will check the
> Java
> > >>>>>>>>>>>> component
> > >>>>>>>>>>>> tree (container.get(tagId)). If there is a miss then we
> search
> > >>>>>>>>>>>> for a
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>   member
> > >>>>>>>>>>>>
> > >>>>>>>>>>>   field that is a component with the same id in the current
> > >>>>>>>>>>>
> > >>>>>>>>>>>>   MarkupContainer,
> > >>>>>>>>>>>>
> > >>>>>>>>>>>   its (Java) super classes and finally in its (Wicket) parent
> > >>>>>>>>>>>
> > >>>>>>>>>>>> classes.
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> This will solve issue #1 (identical trees in Java and
> markup)
> > >>>>>>>>>>>> (P.S. Fridolin's code uses @AutoComponent annotation that
> > >>>>>>>>>>>> facilitates
> > >>>>>>>>>>>> searching by component id, but will duplicate the
> declaration
> > of
> > >>>>>>>>>>>> the id
> > >>>>>>>>>>>> -
> > >>>>>>>>>>>> once in the annotation and second time in 'new
> > MyComponent(ID).
> > >>>>>>>>>>>> This is
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>   an
> > >>>>>>>>>>>>
> > >>>>>>>>>>>   implementation detail.)
> > >>>>>>>>>>>
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> The second part is not less hard - during the walk over the
> > >>>>>>>>>>>> markup tree
> > >>>>>>>>>>>> when an autocomponent (e.g. enclosure) is seen Wicket will
> use
> > >>>>>>>>>>>> the
> > >>>>>>>>>>>> registered IComponentResolvers to create the Java component
> > and
> > >>>>>>>>>>>> insert
> > >>>>>>>>>>>> it
> > >>>>>>>>>>>> in the Java tree.
> > >>>>>>>>>>>> The tricky part here is that any manually added components
> > (like
> > >>>>>>>>>>>> in
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>   Wicket
> > >>>>>>>>>>>>
> > >>>>>>>>>>>   6.x) to the parent of the autocomponent should be moved
> into
> > >>>>>>>>>>> the
> > >>>>>>>>>>>
> > >>>>>>>>>>>> autocomponent.
> > >>>>>>>>>>>> For example:
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> <div wicket:id="a">
> > >>>>>>>>>>>>       <wicket:enclosure child="b">
> > >>>>>>>>>>>>          <span wicket:id="b"></span>
> > >>>>>>>>>>>>          <span wicket:id="c"></span>
> > >>>>>>>>>>>>       </wicket:enclosure>
> > >>>>>>>>>>>> </div>
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> If 'b' and 'c' are added manually to 'a' in the
> application's
> > >>>>>>>>>>>> Java code:
> > >>>>>>>>>>>> (a (b,c))
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> then after the "resolving phase" the tree will be:
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> a (enclosure(b, c))
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> so b.getParent() in onInitialize() and later will return the
> > >>>>>>>>>>>> Enclosure,
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>   not
> > >>>>>>>>>>>>
> > >>>>>>>>>>>   'a'.
> > >>>>>>>>>>>
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> I don't know very well the MarkupStream APIs but I think all
> > >>>>>>>>>>>> this
> > >>>>>>>>>>>> should
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>   be
> > >>>>>>>>>>>>
> > >>>>>>>>>>>   possible.
> > >>>>>>>>>>>
> > >>>>>>>>>>>> WDYT about this approach ?
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> Martin Grigorov
> > >>>>>>>>>>>> Wicket Training and Consulting
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>
> > >>>>>>>>>>>>
> > >
> >
>

Re: Markup driven component tree

Posted by Igor Vaynberg <ig...@gmail.com>.
i just pushed my new idea into sandbox/component-queueing-2

the way this works now is instead of doing it in onInitialize() and in
onConfigure() and all the other places dequeuing now works progressively.
upon a change (container.queue() or component.add()) a dequeue will be
tried.

it even works well with resolved components like enclosures. for such
components the markup of page/panel is traversed in onInitialize() and all
auto components are placed into the queue. later as components are
added/queued these components will be placed into the correct place in the
hierarchy. if queue() is used children of these components will be placed
under them in correct hierarchy place. this is a big win for using queueing
over adding.

repeaters also work. the repeater items themselves have to be added to the
repeater, but item's children can be queued. this is not a problem since
items are mostly added by framework classes.

Borders do not yet work mainly because i havent tried to make them work.
the tricky part there is to keep the border and BorderBody queues separate.

InlineEnclosures do not yet work because the code for figuring out the
value of the child attribute is really convoluted for the simple thing its
supposed to do and i didnt bother parsing it. Should be very similar to how
EnclosureHandler works.

the performance is good. there is ComponentQueueingPerformanceTest with a
disabled test. give it a go and let me know the results. on my box queuing
had under 10% overhead, which is acceptable. I also have some ideas on how
to optimize that further by trading cpu for a bit more memory, but not sure
if its needed since the overhead is low and because its only present when
queuing is used. also the measurements are not too accurate because most of
the time is spent initializing and tearing down a WicketTester instance.

memory overhead is also low, two slots (one of which can/should be
converted to a flag) are added to MarkupContainer.

see ComponentQueuing test for some examples. i would appreciate some help
getting Border and InlineEnclosure working if someone has time.

look over this and lets discuss if/when we should merge it into master.

-igor



On Fri, Jan 31, 2014 at 1:17 AM, Martin Grigorov <mg...@apache.org>wrote:

> Hi Sven,
>
> The component tree rebuilding adds CPU time :-|
> I guess most of the applications would still prefer the current approach
> with the manual construction of the tree in Java land.
>
> Even worse - the rebuilding is needed few times:
> - once before calling Page#onInitialize() so all enqueued children in the
> constructors will have their correct parent and thus their #onInitialize()
> will be called too
> - after Page#onInitialize() because the application may enqueue more
> children in any Component#onInitialize()
> - finally during rendering because a component may get enqueued in
> #onConfigure
>
> Component tree re-arranging is something important too. I have listed it as
> task #2 in my first mail in this thread.
> At the moment the children of an enclosure appear at their correct position
> only with when they are enqueued. More work is needed to support when they
> are added (as in any existing application at the moment).
>
> I'm wondering what idea Igor has. We need to fix the Eclipse settings state
> soon.
>
> On Thu, Jan 30, 2014 at 6:36 PM, Sven Meier <sv...@meiers.net> wrote:
>
> > Hi Martin,
> >
> > if we want markup driven component trees in Wicket, we have to decide
> > whether this is optional or always supported.
> >
> > Currently it's a mix of both: a developer might enqueue components, but
> > they are not used because no listener or behavior rebuilds the container.
> >
> > As it is now, we could equally well make it explicit, i.e. move
> everything
> > into a temporary behavior, that keeps the enqueued components until it is
> > able to rebuild the container:
> >
> >         RebuildBehavior#rebuild(Component... cs);
> >
> >         ComponentA a = new ComponentA("a");
> >         ComponentB b = new ComponentB("b");
> >         ComponentC c = new ComponentC("c");
> >         add(rebuild(a, b, c));
> >
> > What I dislike about an optional solution though: It doesn't solve our
> > issues with non-auto components inside of enclosures. I would prefer a
> > solution which takes care of these too, i.e. it would be able to
> re-arrange
> > already added components.
> >
> >
> > Regards
> > Sven
> >
> >
> > On 01/27/2014 02:14 PM, Martin Grigorov wrote:
> >
> >> I am suspending my work on this because I think there is not enough
> >> interest in this feature at the moment.
> >>
> >> Martin Grigorov
> >> Wicket Training and Consulting
> >>
> >>
> >> On Mon, Jan 27, 2014 at 10:07 AM, Martin Grigorov <mgrigorov@apache.org
> >> >wrote:
> >>
> >>  Reading the archives for Igor's work on "component queueing" I see
> >>>
> >>> Igor Vaynberg<https://issues.apache.org/jira/secure/
> >>> ViewProfile.jspa?name=ivaynberg> added
> >>>
> >>> a comment - 09/Jul/11 23:39
> >>>
> >>> @Juergen, right now your tests only test for rendering, but they should
> >>> also test that before queued component's oninitialize is called the
> >>> component is already a child of the correct parent.
> >>>
> >>>   https://issues.apache.org/jira/browse/WICKET-3335
> >>>
> >>>
> >>> This means that
> >>> org.apache.wicket.application.IComponentInitializationListener cannot
> be
> >>> used. The tree (re)building should happen *before *components'
> >>>
> >>> #onInitialize() and .IComponentInitializationListener#onInitialize() is
> >>> called *after*.
> >>>
> >>> Martin Grigorov
> >>> Wicket Training and Consulting
> >>>
> >>>
> >>> On Fri, Jan 24, 2014 at 2:22 PM, Martin Grigorov <mgrigorov@apache.org
> >>> >wrote:
> >>>
> >>>  I've added alternative ways to use MarkupDrivenComponentTreeBuilder:
> >>>> - with org.apache.wicket.MarkupDrivenTreeInitializionListener
> >>>> - with org.apache.wicket.MarkupDrivenComponentTreeBehavior#onConfigure
> >>>>
> >>>> Both of them do not check the configuration setting whether markup
> >>>> driven
> >>>> tree construction is enabled for now.
> >>>>
> >>>> The approach with MarkupDrivenTreeInitializionListener works the same
> >>>> way
> >>>> as the "inlined" version. The component tree rebuild is activated
> >>>> *after*
> >>>> all Component#onInitialize().
> >>>>
> >>>> The approach with MarkupDrivenComponentTreeBehavior uses
> >>>> #onConfigure().
> >>>> Here I had to change Enclosure class - the child component resolving
> >>>> should
> >>>> be done as late as possible just before the rendering phase starts.
> >>>>
> >>>> Martin Grigorov
> >>>> Wicket Training and Consulting
> >>>>
> >>>>
> >>>> On Fri, Jan 24, 2014 at 11:47 AM, Martin Grigorov <
> mgrigorov@apache.org
> >>>> >wrote:
> >>>>
> >>>>  OK, the new impl is committed.
> >>>>> Now MarkupContainer has #enqueue(Component...) method that adds
> >>>>> components into a list.
> >>>>> Later org.apache.wicket.ComponentTreeBuilder#rebuild() uses the list,
> >>>>> and finally the list is null-yfied in #onDetach() so it is not
> >>>>> serialized
> >>>>> and not available for the next requests. I guess the null-yfing can
> be
> >>>>> done
> >>>>> earlier so even the first request have the extra bytes after the
> >>>>> rebuild of
> >>>>> the tree.
> >>>>>
> >>>>> No need of @Auto anymore.
> >>>>>
> >>>>> Martin Grigorov
> >>>>> Wicket Training and Consulting
> >>>>>
> >>>>>
> >>>>> On Fri, Jan 24, 2014 at 10:39 AM, Martin Grigorov <
> >>>>> mgrigorov@apache.org>wrote:
> >>>>>
> >>>>>
> >>>>>> On Fri, Jan 24, 2014 at 9:48 AM, Sven Meier <sv...@meiers.net>
> wrote:
> >>>>>>
> >>>>>>  per-component basis - yes, as I explained earlier this is possible
> >>>>>>>>
> >>>>>>> with the current impl
> >>>>>>>
> >>>>>>> I must have missed that. Is there an example in the branch?
> >>>>>>>
> >>>>>>>  See
> >>>>>> https://github.com/apache/wicket/blob/markup-driven-
> >>>>>> component-tree/wicket-core/src/main/java/org/apache/
> >>>>>> wicket/MarkupContainer.java?source=c#L1886
> >>>>>> There is no test yet.
> >>>>>>
> >>>>>>
> >>>>>>  I don't understand why there's need for an @Auto annotation. Why
> >>>>>>> would
> >>>>>>> some components be annotated and some not?
> >>>>>>>
> >>>>>>
> >>>>>> The annotation was needed to be able to find the component faster.
> >>>>>> I.e. check only annotated fields. If @Auto(id=...) then use the id
> to
> >>>>>> match against the component tag id.
> >>>>>>
> >>>>>> But with my new idea, the one that will solve the issue with the
> extra
> >>>>>> bytes, this won't be needed anymore.
> >>>>>> Stay tuned.
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   behaviors don't have hooks for onInitialize()
> >>>>>>> It could be done in #onConfigue(), that's early enough.
> >>>>>>>
> >>>>>>
> >>>>>> The problem is that it is called for each request.
> >>>>>> For now I think there is no need to rebuild the component tree for
> >>>>>> each
> >>>>>> request, so we will have to use a guard (e.g. boolean field in the
> >>>>>> component).
> >>>>>> I will consider it.
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   Additionally I think using Behavior will add a bit more bytes to
> >>>>>>> each
> >>>>>>>
> >>>>>>>> component than the current solution
> >>>>>>>>
> >>>>>>>>  I don't think that is a problem: IMHO it's important to make this
> >>>>>>> feature optional, so when users don't use it then they do not pay a
> >>>>>>> price.
> >>>>>>>
> >>>>>>> Regards
> >>>>>>> Sven
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>> On 01/24/2014 06:35 AM, Martin Grigorov wrote:
> >>>>>>>
> >>>>>>>  On Fri, Jan 24, 2014 at 12:04 AM, Sven Meier <sv...@meiers.net>
> >>>>>>>> wrote:
> >>>>>>>>
> >>>>>>>>   Hi,
> >>>>>>>>
> >>>>>>>>> I don't think we're heading the right direction with this and I
> >>>>>>>>> wouldn't
> >>>>>>>>> advertise it as anything yet.
> >>>>>>>>>
> >>>>>>>>>   I'd like to advertise it anyhow now just to have more people
> >>>>>>>>>
> >>>>>>>> feeding me
> >>>>>>>> with stoppers, as you and Igor do. Thanks! :-)
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>   There are more questions to come but here is one upfront:
> >>>>>>>>
> >>>>>>>>>
> >>>>>>>>>   And it is configurable, by default disabled.
> >>>>>>>>> As Igor has written, this does not work with component libraries
> >>>>>>>>> which
> >>>>>>>>> depend on the new feature.
> >>>>>>>>> Couldn't this feature be enabled/disabled on a per-component
> basis?
> >>>>>>>>> Why
> >>>>>>>>> not make it a behavior that you can attach to components if you
> >>>>>>>>> want
> >>>>>>>>> to use
> >>>>>>>>> automatic resolving/rearranging of its children?
> >>>>>>>>>
> >>>>>>>>>   - per-component basis - yes, as I explained earlier this is
> >>>>>>>>>
> >>>>>>>> possible with
> >>>>>>>> the current impl
> >>>>>>>> - behaviors don't have hooks for onInitialize()
> >>>>>>>> After Igor's feedback I think onAfterInitialize() is what is
> needed,
> >>>>>>>> so
> >>>>>>>> apps can use onInitialize() as a complement to the constructor
> >>>>>>>> Additionally I think using Behavior will add a bit more bytes to
> >>>>>>>> each
> >>>>>>>> component than the current solution
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>   Regards
> >>>>>>>>
> >>>>>>>>> Sven
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>> On 01/23/2014 05:20 PM, Martin Grigorov wrote:
> >>>>>>>>>
> >>>>>>>>>   Once the markup driven construction is done (just before
> >>>>>>>>>
> >>>>>>>>>> onInitialize())
> >>>>>>>>>> the application will have to use the old good
> >>>>>>>>>> add()/addOrReplace().
> >>>>>>>>>>
> >>>>>>>>>> The components are already in the MarkupContainer#children data
> >>>>>>>>>> structure.
> >>>>>>>>>> So each field will add extra 8 bytes on 64bit machine (or 4
> bytes
> >>>>>>>>>> with
> >>>>>>>>>> CompressedOops enabled).
> >>>>>>>>>> Serialization is the same - the object is written once, with
> >>>>>>>>>> several
> >>>>>>>>>> pointers.
> >>>>>>>>>>
> >>>>>>>>>> I am also not fully sure in the approach but I am experimenting
> >>>>>>>>>> and
> >>>>>>>>>> so far
> >>>>>>>>>> it works well.
> >>>>>>>>>> And it is configurable, by default disabled.
> >>>>>>>>>> We can advertise it as experimental ?!
> >>>>>>>>>>
> >>>>>>>>>> I will add more use cases/tests soon.
> >>>>>>>>>> And caching for the reflection stuff.
> >>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <
> >>>>>>>>>> igor.vaynberg@gmail.com>
> >>>>>>>>>> wrote:
> >>>>>>>>>>
> >>>>>>>>>>    what about components added in onInitialize() or on
> >>>>>>>>>> onConfigure()?
> >>>>>>>>>>
> >>>>>>>>>>  this will also lead to a higher memory/serialization space
> usage
> >>>>>>>>>>> since
> >>>>>>>>>>> by default you need a field to store the component ref.
> >>>>>>>>>>>
> >>>>>>>>>>> not sure its worth doing it this way...
> >>>>>>>>>>>
> >>>>>>>>>>> -igor
> >>>>>>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <
> >>>>>>>>>>> mgrigorov@apache.org>
> >>>>>>>>>>> wrote:
> >>>>>>>>>>>
> >>>>>>>>>>>   Hi,
> >>>>>>>>>>>
> >>>>>>>>>>>> Recently Fridolin Jackstadt shared his approach to "autowire"
> >>>>>>>>>>>> components
> >>>>>>>>>>>>
> >>>>>>>>>>>>   -
> >>>>>>>>>>>>
> >>>>>>>>>>>   https://github.com/wicket-acc/wicket-autowire.
> >>>>>>>>>>>
> >>>>>>>>>>>> I believe this approach can solve two issues:
> >>>>>>>>>>>> - duplicate construction of the component tree - once in the
> >>>>>>>>>>>> markup and
> >>>>>>>>>>>> second time in Java code
> >>>>>>>>>>>> - auto components available only in the render phase
> >>>>>>>>>>>>
> >>>>>>>>>>>> Here is how I see it:
> >>>>>>>>>>>>
> >>>>>>>>>>>> Any MarkupContainer that wants to use markup-driven-tree must
> >>>>>>>>>>>> declare
> >>>>>>>>>>>> the
> >>>>>>>>>>>> components as member fields:
> >>>>>>>>>>>>
> >>>>>>>>>>>> private SomeComponent aComponent;
> >>>>>>>>>>>>
> >>>>>>>>>>>> These fields will be instantiated like any other component in
> >>>>>>>>>>>> Wicket:
> >>>>>>>>>>>>
> >>>>>>>>>>>> aComponent = new SomeComponent(id, ...);
> >>>>>>>>>>>>
> >>>>>>>>>>>> The new thing is that they *won't* be added to a parent
> >>>>>>>>>>>> component
> >>>>>>>>>>>> explicitly/manually.
> >>>>>>>>>>>>
> >>>>>>>>>>>> On Page#onInitialize() the first thing to do it to walk over
> the
> >>>>>>>>>>>>
> >>>>>>>>>>>>   component
> >>>>>>>>>>>>
> >>>>>>>>>>>   tree from the page's markup (just like the walk in the
> >>>>>>>>>>> rendering
> >>>>>>>>>>>
> >>>>>>>>>>>> related
> >>>>>>>>>>>> code) and resolve the missing bits.
> >>>>>>>>>>>> I.e. while walking thru the markup tree we will check the Java
> >>>>>>>>>>>> component
> >>>>>>>>>>>> tree (container.get(tagId)). If there is a miss then we search
> >>>>>>>>>>>> for a
> >>>>>>>>>>>>
> >>>>>>>>>>>>   member
> >>>>>>>>>>>>
> >>>>>>>>>>>   field that is a component with the same id in the current
> >>>>>>>>>>>
> >>>>>>>>>>>>   MarkupContainer,
> >>>>>>>>>>>>
> >>>>>>>>>>>   its (Java) super classes and finally in its (Wicket) parent
> >>>>>>>>>>>
> >>>>>>>>>>>> classes.
> >>>>>>>>>>>>
> >>>>>>>>>>>> This will solve issue #1 (identical trees in Java and markup)
> >>>>>>>>>>>> (P.S. Fridolin's code uses @AutoComponent annotation that
> >>>>>>>>>>>> facilitates
> >>>>>>>>>>>> searching by component id, but will duplicate the declaration
> of
> >>>>>>>>>>>> the id
> >>>>>>>>>>>> -
> >>>>>>>>>>>> once in the annotation and second time in 'new
> MyComponent(ID).
> >>>>>>>>>>>> This is
> >>>>>>>>>>>>
> >>>>>>>>>>>>   an
> >>>>>>>>>>>>
> >>>>>>>>>>>   implementation detail.)
> >>>>>>>>>>>
> >>>>>>>>>>>>
> >>>>>>>>>>>> The second part is not less hard - during the walk over the
> >>>>>>>>>>>> markup tree
> >>>>>>>>>>>> when an autocomponent (e.g. enclosure) is seen Wicket will use
> >>>>>>>>>>>> the
> >>>>>>>>>>>> registered IComponentResolvers to create the Java component
> and
> >>>>>>>>>>>> insert
> >>>>>>>>>>>> it
> >>>>>>>>>>>> in the Java tree.
> >>>>>>>>>>>> The tricky part here is that any manually added components
> (like
> >>>>>>>>>>>> in
> >>>>>>>>>>>>
> >>>>>>>>>>>>   Wicket
> >>>>>>>>>>>>
> >>>>>>>>>>>   6.x) to the parent of the autocomponent should be moved into
> >>>>>>>>>>> the
> >>>>>>>>>>>
> >>>>>>>>>>>> autocomponent.
> >>>>>>>>>>>> For example:
> >>>>>>>>>>>>
> >>>>>>>>>>>> <div wicket:id="a">
> >>>>>>>>>>>>       <wicket:enclosure child="b">
> >>>>>>>>>>>>          <span wicket:id="b"></span>
> >>>>>>>>>>>>          <span wicket:id="c"></span>
> >>>>>>>>>>>>       </wicket:enclosure>
> >>>>>>>>>>>> </div>
> >>>>>>>>>>>>
> >>>>>>>>>>>> If 'b' and 'c' are added manually to 'a' in the application's
> >>>>>>>>>>>> Java code:
> >>>>>>>>>>>> (a (b,c))
> >>>>>>>>>>>>
> >>>>>>>>>>>> then after the "resolving phase" the tree will be:
> >>>>>>>>>>>>
> >>>>>>>>>>>> a (enclosure(b, c))
> >>>>>>>>>>>>
> >>>>>>>>>>>> so b.getParent() in onInitialize() and later will return the
> >>>>>>>>>>>> Enclosure,
> >>>>>>>>>>>>
> >>>>>>>>>>>>   not
> >>>>>>>>>>>>
> >>>>>>>>>>>   'a'.
> >>>>>>>>>>>
> >>>>>>>>>>>>
> >>>>>>>>>>>> I don't know very well the MarkupStream APIs but I think all
> >>>>>>>>>>>> this
> >>>>>>>>>>>> should
> >>>>>>>>>>>>
> >>>>>>>>>>>>   be
> >>>>>>>>>>>>
> >>>>>>>>>>>   possible.
> >>>>>>>>>>>
> >>>>>>>>>>>> WDYT about this approach ?
> >>>>>>>>>>>>
> >>>>>>>>>>>>
> >>>>>>>>>>>> Martin Grigorov
> >>>>>>>>>>>> Wicket Training and Consulting
> >>>>>>>>>>>>
> >>>>>>>>>>>>
> >>>>>>>>>>>>
> >
>

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
Hi Sven,

The component tree rebuilding adds CPU time :-|
I guess most of the applications would still prefer the current approach
with the manual construction of the tree in Java land.

Even worse - the rebuilding is needed few times:
- once before calling Page#onInitialize() so all enqueued children in the
constructors will have their correct parent and thus their #onInitialize()
will be called too
- after Page#onInitialize() because the application may enqueue more
children in any Component#onInitialize()
- finally during rendering because a component may get enqueued in
#onConfigure

Component tree re-arranging is something important too. I have listed it as
task #2 in my first mail in this thread.
At the moment the children of an enclosure appear at their correct position
only with when they are enqueued. More work is needed to support when they
are added (as in any existing application at the moment).

I'm wondering what idea Igor has. We need to fix the Eclipse settings state
soon.

On Thu, Jan 30, 2014 at 6:36 PM, Sven Meier <sv...@meiers.net> wrote:

> Hi Martin,
>
> if we want markup driven component trees in Wicket, we have to decide
> whether this is optional or always supported.
>
> Currently it's a mix of both: a developer might enqueue components, but
> they are not used because no listener or behavior rebuilds the container.
>
> As it is now, we could equally well make it explicit, i.e. move everything
> into a temporary behavior, that keeps the enqueued components until it is
> able to rebuild the container:
>
>         RebuildBehavior#rebuild(Component... cs);
>
>         ComponentA a = new ComponentA("a");
>         ComponentB b = new ComponentB("b");
>         ComponentC c = new ComponentC("c");
>         add(rebuild(a, b, c));
>
> What I dislike about an optional solution though: It doesn't solve our
> issues with non-auto components inside of enclosures. I would prefer a
> solution which takes care of these too, i.e. it would be able to re-arrange
> already added components.
>
>
> Regards
> Sven
>
>
> On 01/27/2014 02:14 PM, Martin Grigorov wrote:
>
>> I am suspending my work on this because I think there is not enough
>> interest in this feature at the moment.
>>
>> Martin Grigorov
>> Wicket Training and Consulting
>>
>>
>> On Mon, Jan 27, 2014 at 10:07 AM, Martin Grigorov <mgrigorov@apache.org
>> >wrote:
>>
>>  Reading the archives for Igor's work on "component queueing" I see
>>>
>>> Igor Vaynberg<https://issues.apache.org/jira/secure/
>>> ViewProfile.jspa?name=ivaynberg> added
>>>
>>> a comment - 09/Jul/11 23:39
>>>
>>> @Juergen, right now your tests only test for rendering, but they should
>>> also test that before queued component's oninitialize is called the
>>> component is already a child of the correct parent.
>>>
>>>   https://issues.apache.org/jira/browse/WICKET-3335
>>>
>>>
>>> This means that
>>> org.apache.wicket.application.IComponentInitializationListener cannot be
>>> used. The tree (re)building should happen *before *components'
>>>
>>> #onInitialize() and .IComponentInitializationListener#onInitialize() is
>>> called *after*.
>>>
>>> Martin Grigorov
>>> Wicket Training and Consulting
>>>
>>>
>>> On Fri, Jan 24, 2014 at 2:22 PM, Martin Grigorov <mgrigorov@apache.org
>>> >wrote:
>>>
>>>  I've added alternative ways to use MarkupDrivenComponentTreeBuilder:
>>>> - with org.apache.wicket.MarkupDrivenTreeInitializionListener
>>>> - with org.apache.wicket.MarkupDrivenComponentTreeBehavior#onConfigure
>>>>
>>>> Both of them do not check the configuration setting whether markup
>>>> driven
>>>> tree construction is enabled for now.
>>>>
>>>> The approach with MarkupDrivenTreeInitializionListener works the same
>>>> way
>>>> as the "inlined" version. The component tree rebuild is activated
>>>> *after*
>>>> all Component#onInitialize().
>>>>
>>>> The approach with MarkupDrivenComponentTreeBehavior uses
>>>> #onConfigure().
>>>> Here I had to change Enclosure class - the child component resolving
>>>> should
>>>> be done as late as possible just before the rendering phase starts.
>>>>
>>>> Martin Grigorov
>>>> Wicket Training and Consulting
>>>>
>>>>
>>>> On Fri, Jan 24, 2014 at 11:47 AM, Martin Grigorov <mgrigorov@apache.org
>>>> >wrote:
>>>>
>>>>  OK, the new impl is committed.
>>>>> Now MarkupContainer has #enqueue(Component...) method that adds
>>>>> components into a list.
>>>>> Later org.apache.wicket.ComponentTreeBuilder#rebuild() uses the list,
>>>>> and finally the list is null-yfied in #onDetach() so it is not
>>>>> serialized
>>>>> and not available for the next requests. I guess the null-yfing can be
>>>>> done
>>>>> earlier so even the first request have the extra bytes after the
>>>>> rebuild of
>>>>> the tree.
>>>>>
>>>>> No need of @Auto anymore.
>>>>>
>>>>> Martin Grigorov
>>>>> Wicket Training and Consulting
>>>>>
>>>>>
>>>>> On Fri, Jan 24, 2014 at 10:39 AM, Martin Grigorov <
>>>>> mgrigorov@apache.org>wrote:
>>>>>
>>>>>
>>>>>> On Fri, Jan 24, 2014 at 9:48 AM, Sven Meier <sv...@meiers.net> wrote:
>>>>>>
>>>>>>  per-component basis - yes, as I explained earlier this is possible
>>>>>>>>
>>>>>>> with the current impl
>>>>>>>
>>>>>>> I must have missed that. Is there an example in the branch?
>>>>>>>
>>>>>>>  See
>>>>>> https://github.com/apache/wicket/blob/markup-driven-
>>>>>> component-tree/wicket-core/src/main/java/org/apache/
>>>>>> wicket/MarkupContainer.java?source=c#L1886
>>>>>> There is no test yet.
>>>>>>
>>>>>>
>>>>>>  I don't understand why there's need for an @Auto annotation. Why
>>>>>>> would
>>>>>>> some components be annotated and some not?
>>>>>>>
>>>>>>
>>>>>> The annotation was needed to be able to find the component faster.
>>>>>> I.e. check only annotated fields. If @Auto(id=...) then use the id to
>>>>>> match against the component tag id.
>>>>>>
>>>>>> But with my new idea, the one that will solve the issue with the extra
>>>>>> bytes, this won't be needed anymore.
>>>>>> Stay tuned.
>>>>>>
>>>>>>
>>>>>>
>>>>>>>   behaviors don't have hooks for onInitialize()
>>>>>>> It could be done in #onConfigue(), that's early enough.
>>>>>>>
>>>>>>
>>>>>> The problem is that it is called for each request.
>>>>>> For now I think there is no need to rebuild the component tree for
>>>>>> each
>>>>>> request, so we will have to use a guard (e.g. boolean field in the
>>>>>> component).
>>>>>> I will consider it.
>>>>>>
>>>>>>
>>>>>>
>>>>>>>   Additionally I think using Behavior will add a bit more bytes to
>>>>>>> each
>>>>>>>
>>>>>>>> component than the current solution
>>>>>>>>
>>>>>>>>  I don't think that is a problem: IMHO it's important to make this
>>>>>>> feature optional, so when users don't use it then they do not pay a
>>>>>>> price.
>>>>>>>
>>>>>>> Regards
>>>>>>> Sven
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 01/24/2014 06:35 AM, Martin Grigorov wrote:
>>>>>>>
>>>>>>>  On Fri, Jan 24, 2014 at 12:04 AM, Sven Meier <sv...@meiers.net>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>   Hi,
>>>>>>>>
>>>>>>>>> I don't think we're heading the right direction with this and I
>>>>>>>>> wouldn't
>>>>>>>>> advertise it as anything yet.
>>>>>>>>>
>>>>>>>>>   I'd like to advertise it anyhow now just to have more people
>>>>>>>>>
>>>>>>>> feeding me
>>>>>>>> with stoppers, as you and Igor do. Thanks! :-)
>>>>>>>>
>>>>>>>>
>>>>>>>>   There are more questions to come but here is one upfront:
>>>>>>>>
>>>>>>>>>
>>>>>>>>>   And it is configurable, by default disabled.
>>>>>>>>> As Igor has written, this does not work with component libraries
>>>>>>>>> which
>>>>>>>>> depend on the new feature.
>>>>>>>>> Couldn't this feature be enabled/disabled on a per-component basis?
>>>>>>>>> Why
>>>>>>>>> not make it a behavior that you can attach to components if you
>>>>>>>>> want
>>>>>>>>> to use
>>>>>>>>> automatic resolving/rearranging of its children?
>>>>>>>>>
>>>>>>>>>   - per-component basis - yes, as I explained earlier this is
>>>>>>>>>
>>>>>>>> possible with
>>>>>>>> the current impl
>>>>>>>> - behaviors don't have hooks for onInitialize()
>>>>>>>> After Igor's feedback I think onAfterInitialize() is what is needed,
>>>>>>>> so
>>>>>>>> apps can use onInitialize() as a complement to the constructor
>>>>>>>> Additionally I think using Behavior will add a bit more bytes to
>>>>>>>> each
>>>>>>>> component than the current solution
>>>>>>>>
>>>>>>>>
>>>>>>>>   Regards
>>>>>>>>
>>>>>>>>> Sven
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 01/23/2014 05:20 PM, Martin Grigorov wrote:
>>>>>>>>>
>>>>>>>>>   Once the markup driven construction is done (just before
>>>>>>>>>
>>>>>>>>>> onInitialize())
>>>>>>>>>> the application will have to use the old good
>>>>>>>>>> add()/addOrReplace().
>>>>>>>>>>
>>>>>>>>>> The components are already in the MarkupContainer#children data
>>>>>>>>>> structure.
>>>>>>>>>> So each field will add extra 8 bytes on 64bit machine (or 4 bytes
>>>>>>>>>> with
>>>>>>>>>> CompressedOops enabled).
>>>>>>>>>> Serialization is the same - the object is written once, with
>>>>>>>>>> several
>>>>>>>>>> pointers.
>>>>>>>>>>
>>>>>>>>>> I am also not fully sure in the approach but I am experimenting
>>>>>>>>>> and
>>>>>>>>>> so far
>>>>>>>>>> it works well.
>>>>>>>>>> And it is configurable, by default disabled.
>>>>>>>>>> We can advertise it as experimental ?!
>>>>>>>>>>
>>>>>>>>>> I will add more use cases/tests soon.
>>>>>>>>>> And caching for the reflection stuff.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <
>>>>>>>>>> igor.vaynberg@gmail.com>
>>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>>    what about components added in onInitialize() or on
>>>>>>>>>> onConfigure()?
>>>>>>>>>>
>>>>>>>>>>  this will also lead to a higher memory/serialization space usage
>>>>>>>>>>> since
>>>>>>>>>>> by default you need a field to store the component ref.
>>>>>>>>>>>
>>>>>>>>>>> not sure its worth doing it this way...
>>>>>>>>>>>
>>>>>>>>>>> -igor
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <
>>>>>>>>>>> mgrigorov@apache.org>
>>>>>>>>>>> wrote:
>>>>>>>>>>>
>>>>>>>>>>>   Hi,
>>>>>>>>>>>
>>>>>>>>>>>> Recently Fridolin Jackstadt shared his approach to "autowire"
>>>>>>>>>>>> components
>>>>>>>>>>>>
>>>>>>>>>>>>   -
>>>>>>>>>>>>
>>>>>>>>>>>   https://github.com/wicket-acc/wicket-autowire.
>>>>>>>>>>>
>>>>>>>>>>>> I believe this approach can solve two issues:
>>>>>>>>>>>> - duplicate construction of the component tree - once in the
>>>>>>>>>>>> markup and
>>>>>>>>>>>> second time in Java code
>>>>>>>>>>>> - auto components available only in the render phase
>>>>>>>>>>>>
>>>>>>>>>>>> Here is how I see it:
>>>>>>>>>>>>
>>>>>>>>>>>> Any MarkupContainer that wants to use markup-driven-tree must
>>>>>>>>>>>> declare
>>>>>>>>>>>> the
>>>>>>>>>>>> components as member fields:
>>>>>>>>>>>>
>>>>>>>>>>>> private SomeComponent aComponent;
>>>>>>>>>>>>
>>>>>>>>>>>> These fields will be instantiated like any other component in
>>>>>>>>>>>> Wicket:
>>>>>>>>>>>>
>>>>>>>>>>>> aComponent = new SomeComponent(id, ...);
>>>>>>>>>>>>
>>>>>>>>>>>> The new thing is that they *won't* be added to a parent
>>>>>>>>>>>> component
>>>>>>>>>>>> explicitly/manually.
>>>>>>>>>>>>
>>>>>>>>>>>> On Page#onInitialize() the first thing to do it to walk over the
>>>>>>>>>>>>
>>>>>>>>>>>>   component
>>>>>>>>>>>>
>>>>>>>>>>>   tree from the page's markup (just like the walk in the
>>>>>>>>>>> rendering
>>>>>>>>>>>
>>>>>>>>>>>> related
>>>>>>>>>>>> code) and resolve the missing bits.
>>>>>>>>>>>> I.e. while walking thru the markup tree we will check the Java
>>>>>>>>>>>> component
>>>>>>>>>>>> tree (container.get(tagId)). If there is a miss then we search
>>>>>>>>>>>> for a
>>>>>>>>>>>>
>>>>>>>>>>>>   member
>>>>>>>>>>>>
>>>>>>>>>>>   field that is a component with the same id in the current
>>>>>>>>>>>
>>>>>>>>>>>>   MarkupContainer,
>>>>>>>>>>>>
>>>>>>>>>>>   its (Java) super classes and finally in its (Wicket) parent
>>>>>>>>>>>
>>>>>>>>>>>> classes.
>>>>>>>>>>>>
>>>>>>>>>>>> This will solve issue #1 (identical trees in Java and markup)
>>>>>>>>>>>> (P.S. Fridolin's code uses @AutoComponent annotation that
>>>>>>>>>>>> facilitates
>>>>>>>>>>>> searching by component id, but will duplicate the declaration of
>>>>>>>>>>>> the id
>>>>>>>>>>>> -
>>>>>>>>>>>> once in the annotation and second time in 'new MyComponent(ID).
>>>>>>>>>>>> This is
>>>>>>>>>>>>
>>>>>>>>>>>>   an
>>>>>>>>>>>>
>>>>>>>>>>>   implementation detail.)
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> The second part is not less hard - during the walk over the
>>>>>>>>>>>> markup tree
>>>>>>>>>>>> when an autocomponent (e.g. enclosure) is seen Wicket will use
>>>>>>>>>>>> the
>>>>>>>>>>>> registered IComponentResolvers to create the Java component and
>>>>>>>>>>>> insert
>>>>>>>>>>>> it
>>>>>>>>>>>> in the Java tree.
>>>>>>>>>>>> The tricky part here is that any manually added components (like
>>>>>>>>>>>> in
>>>>>>>>>>>>
>>>>>>>>>>>>   Wicket
>>>>>>>>>>>>
>>>>>>>>>>>   6.x) to the parent of the autocomponent should be moved into
>>>>>>>>>>> the
>>>>>>>>>>>
>>>>>>>>>>>> autocomponent.
>>>>>>>>>>>> For example:
>>>>>>>>>>>>
>>>>>>>>>>>> <div wicket:id="a">
>>>>>>>>>>>>       <wicket:enclosure child="b">
>>>>>>>>>>>>          <span wicket:id="b"></span>
>>>>>>>>>>>>          <span wicket:id="c"></span>
>>>>>>>>>>>>       </wicket:enclosure>
>>>>>>>>>>>> </div>
>>>>>>>>>>>>
>>>>>>>>>>>> If 'b' and 'c' are added manually to 'a' in the application's
>>>>>>>>>>>> Java code:
>>>>>>>>>>>> (a (b,c))
>>>>>>>>>>>>
>>>>>>>>>>>> then after the "resolving phase" the tree will be:
>>>>>>>>>>>>
>>>>>>>>>>>> a (enclosure(b, c))
>>>>>>>>>>>>
>>>>>>>>>>>> so b.getParent() in onInitialize() and later will return the
>>>>>>>>>>>> Enclosure,
>>>>>>>>>>>>
>>>>>>>>>>>>   not
>>>>>>>>>>>>
>>>>>>>>>>>   'a'.
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> I don't know very well the MarkupStream APIs but I think all
>>>>>>>>>>>> this
>>>>>>>>>>>> should
>>>>>>>>>>>>
>>>>>>>>>>>>   be
>>>>>>>>>>>>
>>>>>>>>>>>   possible.
>>>>>>>>>>>
>>>>>>>>>>>> WDYT about this approach ?
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Martin Grigorov
>>>>>>>>>>>> Wicket Training and Consulting
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>

Re: Markup driven component tree

Posted by Sven Meier <sv...@meiers.net>.
Hi Martin,

if we want markup driven component trees in Wicket, we have to decide 
whether this is optional or always supported.

Currently it's a mix of both: a developer might enqueue components, but 
they are not used because no listener or behavior rebuilds the container.

As it is now, we could equally well make it explicit, i.e. move 
everything into a temporary behavior, that keeps the enqueued components 
until it is able to rebuild the container:

         RebuildBehavior#rebuild(Component... cs);

         ComponentA a = new ComponentA("a");
         ComponentB b = new ComponentB("b");
         ComponentC c = new ComponentC("c");
         add(rebuild(a, b, c));

What I dislike about an optional solution though: It doesn't solve our 
issues with non-auto components inside of enclosures. I would prefer a 
solution which takes care of these too, i.e. it would be able to 
re-arrange already added components.

Regards
Sven


On 01/27/2014 02:14 PM, Martin Grigorov wrote:
> I am suspending my work on this because I think there is not enough
> interest in this feature at the moment.
>
> Martin Grigorov
> Wicket Training and Consulting
>
>
> On Mon, Jan 27, 2014 at 10:07 AM, Martin Grigorov <mg...@apache.org>wrote:
>
>> Reading the archives for Igor's work on "component queueing" I see
>>
>> Igor Vaynberg<https://issues.apache.org/jira/secure/ViewProfile.jspa?name=ivaynberg> added
>> a comment - 09/Jul/11 23:39
>>
>> @Juergen, right now your tests only test for rendering, but they should
>> also test that before queued component's oninitialize is called the
>> component is already a child of the correct parent.
>>
>>   https://issues.apache.org/jira/browse/WICKET-3335
>>
>>
>> This means that
>> org.apache.wicket.application.IComponentInitializationListener cannot be
>> used. The tree (re)building should happen *before *components'
>> #onInitialize() and .IComponentInitializationListener#onInitialize() is
>> called *after*.
>>
>> Martin Grigorov
>> Wicket Training and Consulting
>>
>>
>> On Fri, Jan 24, 2014 at 2:22 PM, Martin Grigorov <mg...@apache.org>wrote:
>>
>>> I've added alternative ways to use MarkupDrivenComponentTreeBuilder:
>>> - with org.apache.wicket.MarkupDrivenTreeInitializionListener
>>> - with org.apache.wicket.MarkupDrivenComponentTreeBehavior#onConfigure
>>>
>>> Both of them do not check the configuration setting whether markup driven
>>> tree construction is enabled for now.
>>>
>>> The approach with MarkupDrivenTreeInitializionListener works the same way
>>> as the "inlined" version. The component tree rebuild is activated *after*
>>> all Component#onInitialize().
>>>
>>> The approach with MarkupDrivenComponentTreeBehavior uses #onConfigure().
>>> Here I had to change Enclosure class - the child component resolving should
>>> be done as late as possible just before the rendering phase starts.
>>>
>>> Martin Grigorov
>>> Wicket Training and Consulting
>>>
>>>
>>> On Fri, Jan 24, 2014 at 11:47 AM, Martin Grigorov <mg...@apache.org>wrote:
>>>
>>>> OK, the new impl is committed.
>>>> Now MarkupContainer has #enqueue(Component...) method that adds
>>>> components into a list.
>>>> Later org.apache.wicket.ComponentTreeBuilder#rebuild() uses the list,
>>>> and finally the list is null-yfied in #onDetach() so it is not serialized
>>>> and not available for the next requests. I guess the null-yfing can be done
>>>> earlier so even the first request have the extra bytes after the rebuild of
>>>> the tree.
>>>>
>>>> No need of @Auto anymore.
>>>>
>>>> Martin Grigorov
>>>> Wicket Training and Consulting
>>>>
>>>>
>>>> On Fri, Jan 24, 2014 at 10:39 AM, Martin Grigorov <mg...@apache.org>wrote:
>>>>
>>>>>
>>>>> On Fri, Jan 24, 2014 at 9:48 AM, Sven Meier <sv...@meiers.net> wrote:
>>>>>
>>>>>>> per-component basis - yes, as I explained earlier this is possible
>>>>>> with the current impl
>>>>>>
>>>>>> I must have missed that. Is there an example in the branch?
>>>>>>
>>>>> See
>>>>> https://github.com/apache/wicket/blob/markup-driven-component-tree/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java?source=c#L1886
>>>>> There is no test yet.
>>>>>
>>>>>
>>>>>> I don't understand why there's need for an @Auto annotation. Why would
>>>>>> some components be annotated and some not?
>>>>>
>>>>> The annotation was needed to be able to find the component faster.
>>>>> I.e. check only annotated fields. If @Auto(id=...) then use the id to
>>>>> match against the component tag id.
>>>>>
>>>>> But with my new idea, the one that will solve the issue with the extra
>>>>> bytes, this won't be needed anymore.
>>>>> Stay tuned.
>>>>>
>>>>>
>>>>>>
>>>>>>   behaviors don't have hooks for onInitialize()
>>>>>> It could be done in #onConfigue(), that's early enough.
>>>>>
>>>>> The problem is that it is called for each request.
>>>>> For now I think there is no need to rebuild the component tree for each
>>>>> request, so we will have to use a guard (e.g. boolean field in the
>>>>> component).
>>>>> I will consider it.
>>>>>
>>>>>
>>>>>>
>>>>>>   Additionally I think using Behavior will add a bit more bytes to each
>>>>>>> component than the current solution
>>>>>>>
>>>>>> I don't think that is a problem: IMHO it's important to make this
>>>>>> feature optional, so when users don't use it then they do not pay a price.
>>>>>>
>>>>>> Regards
>>>>>> Sven
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 01/24/2014 06:35 AM, Martin Grigorov wrote:
>>>>>>
>>>>>>> On Fri, Jan 24, 2014 at 12:04 AM, Sven Meier <sv...@meiers.net> wrote:
>>>>>>>
>>>>>>>   Hi,
>>>>>>>> I don't think we're heading the right direction with this and I
>>>>>>>> wouldn't
>>>>>>>> advertise it as anything yet.
>>>>>>>>
>>>>>>>>   I'd like to advertise it anyhow now just to have more people
>>>>>>> feeding me
>>>>>>> with stoppers, as you and Igor do. Thanks! :-)
>>>>>>>
>>>>>>>
>>>>>>>   There are more questions to come but here is one upfront:
>>>>>>>>
>>>>>>>>   And it is configurable, by default disabled.
>>>>>>>> As Igor has written, this does not work with component libraries
>>>>>>>> which
>>>>>>>> depend on the new feature.
>>>>>>>> Couldn't this feature be enabled/disabled on a per-component basis?
>>>>>>>> Why
>>>>>>>> not make it a behavior that you can attach to components if you want
>>>>>>>> to use
>>>>>>>> automatic resolving/rearranging of its children?
>>>>>>>>
>>>>>>>>   - per-component basis - yes, as I explained earlier this is
>>>>>>> possible with
>>>>>>> the current impl
>>>>>>> - behaviors don't have hooks for onInitialize()
>>>>>>> After Igor's feedback I think onAfterInitialize() is what is needed,
>>>>>>> so
>>>>>>> apps can use onInitialize() as a complement to the constructor
>>>>>>> Additionally I think using Behavior will add a bit more bytes to each
>>>>>>> component than the current solution
>>>>>>>
>>>>>>>
>>>>>>>   Regards
>>>>>>>> Sven
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On 01/23/2014 05:20 PM, Martin Grigorov wrote:
>>>>>>>>
>>>>>>>>   Once the markup driven construction is done (just before
>>>>>>>>> onInitialize())
>>>>>>>>> the application will have to use the old good add()/addOrReplace().
>>>>>>>>>
>>>>>>>>> The components are already in the MarkupContainer#children data
>>>>>>>>> structure.
>>>>>>>>> So each field will add extra 8 bytes on 64bit machine (or 4 bytes
>>>>>>>>> with
>>>>>>>>> CompressedOops enabled).
>>>>>>>>> Serialization is the same - the object is written once, with several
>>>>>>>>> pointers.
>>>>>>>>>
>>>>>>>>> I am also not fully sure in the approach but I am experimenting and
>>>>>>>>> so far
>>>>>>>>> it works well.
>>>>>>>>> And it is configurable, by default disabled.
>>>>>>>>> We can advertise it as experimental ?!
>>>>>>>>>
>>>>>>>>> I will add more use cases/tests soon.
>>>>>>>>> And caching for the reflection stuff.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <
>>>>>>>>> igor.vaynberg@gmail.com>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>    what about components added in onInitialize() or on onConfigure()?
>>>>>>>>>
>>>>>>>>>> this will also lead to a higher memory/serialization space usage
>>>>>>>>>> since
>>>>>>>>>> by default you need a field to store the component ref.
>>>>>>>>>>
>>>>>>>>>> not sure its worth doing it this way...
>>>>>>>>>>
>>>>>>>>>> -igor
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <
>>>>>>>>>> mgrigorov@apache.org>
>>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>>   Hi,
>>>>>>>>>>> Recently Fridolin Jackstadt shared his approach to "autowire"
>>>>>>>>>>> components
>>>>>>>>>>>
>>>>>>>>>>>   -
>>>>>>>>>>   https://github.com/wicket-acc/wicket-autowire.
>>>>>>>>>>> I believe this approach can solve two issues:
>>>>>>>>>>> - duplicate construction of the component tree - once in the
>>>>>>>>>>> markup and
>>>>>>>>>>> second time in Java code
>>>>>>>>>>> - auto components available only in the render phase
>>>>>>>>>>>
>>>>>>>>>>> Here is how I see it:
>>>>>>>>>>>
>>>>>>>>>>> Any MarkupContainer that wants to use markup-driven-tree must
>>>>>>>>>>> declare
>>>>>>>>>>> the
>>>>>>>>>>> components as member fields:
>>>>>>>>>>>
>>>>>>>>>>> private SomeComponent aComponent;
>>>>>>>>>>>
>>>>>>>>>>> These fields will be instantiated like any other component in
>>>>>>>>>>> Wicket:
>>>>>>>>>>>
>>>>>>>>>>> aComponent = new SomeComponent(id, ...);
>>>>>>>>>>>
>>>>>>>>>>> The new thing is that they *won't* be added to a parent component
>>>>>>>>>>> explicitly/manually.
>>>>>>>>>>>
>>>>>>>>>>> On Page#onInitialize() the first thing to do it to walk over the
>>>>>>>>>>>
>>>>>>>>>>>   component
>>>>>>>>>>   tree from the page's markup (just like the walk in the rendering
>>>>>>>>>>> related
>>>>>>>>>>> code) and resolve the missing bits.
>>>>>>>>>>> I.e. while walking thru the markup tree we will check the Java
>>>>>>>>>>> component
>>>>>>>>>>> tree (container.get(tagId)). If there is a miss then we search
>>>>>>>>>>> for a
>>>>>>>>>>>
>>>>>>>>>>>   member
>>>>>>>>>>   field that is a component with the same id in the current
>>>>>>>>>>>   MarkupContainer,
>>>>>>>>>>   its (Java) super classes and finally in its (Wicket) parent
>>>>>>>>>>> classes.
>>>>>>>>>>>
>>>>>>>>>>> This will solve issue #1 (identical trees in Java and markup)
>>>>>>>>>>> (P.S. Fridolin's code uses @AutoComponent annotation that
>>>>>>>>>>> facilitates
>>>>>>>>>>> searching by component id, but will duplicate the declaration of
>>>>>>>>>>> the id
>>>>>>>>>>> -
>>>>>>>>>>> once in the annotation and second time in 'new MyComponent(ID).
>>>>>>>>>>> This is
>>>>>>>>>>>
>>>>>>>>>>>   an
>>>>>>>>>>   implementation detail.)
>>>>>>>>>>>
>>>>>>>>>>> The second part is not less hard - during the walk over the
>>>>>>>>>>> markup tree
>>>>>>>>>>> when an autocomponent (e.g. enclosure) is seen Wicket will use the
>>>>>>>>>>> registered IComponentResolvers to create the Java component and
>>>>>>>>>>> insert
>>>>>>>>>>> it
>>>>>>>>>>> in the Java tree.
>>>>>>>>>>> The tricky part here is that any manually added components (like
>>>>>>>>>>> in
>>>>>>>>>>>
>>>>>>>>>>>   Wicket
>>>>>>>>>>   6.x) to the parent of the autocomponent should be moved into the
>>>>>>>>>>> autocomponent.
>>>>>>>>>>> For example:
>>>>>>>>>>>
>>>>>>>>>>> <div wicket:id="a">
>>>>>>>>>>>       <wicket:enclosure child="b">
>>>>>>>>>>>          <span wicket:id="b"></span>
>>>>>>>>>>>          <span wicket:id="c"></span>
>>>>>>>>>>>       </wicket:enclosure>
>>>>>>>>>>> </div>
>>>>>>>>>>>
>>>>>>>>>>> If 'b' and 'c' are added manually to 'a' in the application's
>>>>>>>>>>> Java code:
>>>>>>>>>>> (a (b,c))
>>>>>>>>>>>
>>>>>>>>>>> then after the "resolving phase" the tree will be:
>>>>>>>>>>>
>>>>>>>>>>> a (enclosure(b, c))
>>>>>>>>>>>
>>>>>>>>>>> so b.getParent() in onInitialize() and later will return the
>>>>>>>>>>> Enclosure,
>>>>>>>>>>>
>>>>>>>>>>>   not
>>>>>>>>>>   'a'.
>>>>>>>>>>>
>>>>>>>>>>> I don't know very well the MarkupStream APIs but I think all this
>>>>>>>>>>> should
>>>>>>>>>>>
>>>>>>>>>>>   be
>>>>>>>>>>   possible.
>>>>>>>>>>> WDYT about this approach ?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Martin Grigorov
>>>>>>>>>>> Wicket Training and Consulting
>>>>>>>>>>>
>>>>>>>>>>>


Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
I am suspending my work on this because I think there is not enough
interest in this feature at the moment.

Martin Grigorov
Wicket Training and Consulting


On Mon, Jan 27, 2014 at 10:07 AM, Martin Grigorov <mg...@apache.org>wrote:

> Reading the archives for Igor's work on "component queueing" I see
>
> Igor Vaynberg<https://issues.apache.org/jira/secure/ViewProfile.jspa?name=ivaynberg> added
> a comment - 09/Jul/11 23:39
>
> @Juergen, right now your tests only test for rendering, but they should
> also test that before queued component's oninitialize is called the
> component is already a child of the correct parent.
>
>  https://issues.apache.org/jira/browse/WICKET-3335
>
>
> This means that
> org.apache.wicket.application.IComponentInitializationListener cannot be
> used. The tree (re)building should happen *before *components'
> #onInitialize() and .IComponentInitializationListener#onInitialize() is
> called *after*.
>
> Martin Grigorov
> Wicket Training and Consulting
>
>
> On Fri, Jan 24, 2014 at 2:22 PM, Martin Grigorov <mg...@apache.org>wrote:
>
>> I've added alternative ways to use MarkupDrivenComponentTreeBuilder:
>> - with org.apache.wicket.MarkupDrivenTreeInitializionListener
>> - with org.apache.wicket.MarkupDrivenComponentTreeBehavior#onConfigure
>>
>> Both of them do not check the configuration setting whether markup driven
>> tree construction is enabled for now.
>>
>> The approach with MarkupDrivenTreeInitializionListener works the same way
>> as the "inlined" version. The component tree rebuild is activated *after*
>> all Component#onInitialize().
>>
>> The approach with MarkupDrivenComponentTreeBehavior uses #onConfigure().
>> Here I had to change Enclosure class - the child component resolving should
>> be done as late as possible just before the rendering phase starts.
>>
>> Martin Grigorov
>> Wicket Training and Consulting
>>
>>
>> On Fri, Jan 24, 2014 at 11:47 AM, Martin Grigorov <mg...@apache.org>wrote:
>>
>>> OK, the new impl is committed.
>>> Now MarkupContainer has #enqueue(Component...) method that adds
>>> components into a list.
>>> Later org.apache.wicket.ComponentTreeBuilder#rebuild() uses the list,
>>> and finally the list is null-yfied in #onDetach() so it is not serialized
>>> and not available for the next requests. I guess the null-yfing can be done
>>> earlier so even the first request have the extra bytes after the rebuild of
>>> the tree.
>>>
>>> No need of @Auto anymore.
>>>
>>> Martin Grigorov
>>> Wicket Training and Consulting
>>>
>>>
>>> On Fri, Jan 24, 2014 at 10:39 AM, Martin Grigorov <mg...@apache.org>wrote:
>>>
>>>>
>>>>
>>>> On Fri, Jan 24, 2014 at 9:48 AM, Sven Meier <sv...@meiers.net> wrote:
>>>>
>>>>> > per-component basis - yes, as I explained earlier this is possible
>>>>> with the current impl
>>>>>
>>>>> I must have missed that. Is there an example in the branch?
>>>>>
>>>>
>>>> See
>>>> https://github.com/apache/wicket/blob/markup-driven-component-tree/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java?source=c#L1886
>>>> There is no test yet.
>>>>
>>>>
>>>>>
>>>>> I don't understand why there's need for an @Auto annotation. Why would
>>>>> some components be annotated and some not?
>>>>
>>>>
>>>> The annotation was needed to be able to find the component faster.
>>>> I.e. check only annotated fields. If @Auto(id=...) then use the id to
>>>> match against the component tag id.
>>>>
>>>> But with my new idea, the one that will solve the issue with the extra
>>>> bytes, this won't be needed anymore.
>>>> Stay tuned.
>>>>
>>>>
>>>>>
>>>>>
>>>>>  behaviors don't have hooks for onInitialize()
>>>>>>
>>>>>
>>>>> It could be done in #onConfigue(), that's early enough.
>>>>
>>>>
>>>> The problem is that it is called for each request.
>>>> For now I think there is no need to rebuild the component tree for each
>>>> request, so we will have to use a guard (e.g. boolean field in the
>>>> component).
>>>> I will consider it.
>>>>
>>>>
>>>>>
>>>>>
>>>>>  Additionally I think using Behavior will add a bit more bytes to each
>>>>>> component than the current solution
>>>>>>
>>>>>
>>>>> I don't think that is a problem: IMHO it's important to make this
>>>>> feature optional, so when users don't use it then they do not pay a price.
>>>>>
>>>>> Regards
>>>>> Sven
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On 01/24/2014 06:35 AM, Martin Grigorov wrote:
>>>>>
>>>>>> On Fri, Jan 24, 2014 at 12:04 AM, Sven Meier <sv...@meiers.net> wrote:
>>>>>>
>>>>>>  Hi,
>>>>>>>
>>>>>>> I don't think we're heading the right direction with this and I
>>>>>>> wouldn't
>>>>>>> advertise it as anything yet.
>>>>>>>
>>>>>>>  I'd like to advertise it anyhow now just to have more people
>>>>>> feeding me
>>>>>> with stoppers, as you and Igor do. Thanks! :-)
>>>>>>
>>>>>>
>>>>>>  There are more questions to come but here is one upfront:
>>>>>>>
>>>>>>>
>>>>>>>  And it is configurable, by default disabled.
>>>>>>>>
>>>>>>> As Igor has written, this does not work with component libraries
>>>>>>> which
>>>>>>> depend on the new feature.
>>>>>>> Couldn't this feature be enabled/disabled on a per-component basis?
>>>>>>> Why
>>>>>>> not make it a behavior that you can attach to components if you want
>>>>>>> to use
>>>>>>> automatic resolving/rearranging of its children?
>>>>>>>
>>>>>>>  - per-component basis - yes, as I explained earlier this is
>>>>>> possible with
>>>>>> the current impl
>>>>>> - behaviors don't have hooks for onInitialize()
>>>>>> After Igor's feedback I think onAfterInitialize() is what is needed,
>>>>>> so
>>>>>> apps can use onInitialize() as a complement to the constructor
>>>>>> Additionally I think using Behavior will add a bit more bytes to each
>>>>>> component than the current solution
>>>>>>
>>>>>>
>>>>>>  Regards
>>>>>>> Sven
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 01/23/2014 05:20 PM, Martin Grigorov wrote:
>>>>>>>
>>>>>>>  Once the markup driven construction is done (just before
>>>>>>>> onInitialize())
>>>>>>>> the application will have to use the old good add()/addOrReplace().
>>>>>>>>
>>>>>>>> The components are already in the MarkupContainer#children data
>>>>>>>> structure.
>>>>>>>> So each field will add extra 8 bytes on 64bit machine (or 4 bytes
>>>>>>>> with
>>>>>>>> CompressedOops enabled).
>>>>>>>> Serialization is the same - the object is written once, with several
>>>>>>>> pointers.
>>>>>>>>
>>>>>>>> I am also not fully sure in the approach but I am experimenting and
>>>>>>>> so far
>>>>>>>> it works well.
>>>>>>>> And it is configurable, by default disabled.
>>>>>>>> We can advertise it as experimental ?!
>>>>>>>>
>>>>>>>> I will add more use cases/tests soon.
>>>>>>>> And caching for the reflection stuff.
>>>>>>>>
>>>>>>>>
>>>>>>>> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <
>>>>>>>> igor.vaynberg@gmail.com>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>   what about components added in onInitialize() or on onConfigure()?
>>>>>>>>
>>>>>>>>> this will also lead to a higher memory/serialization space usage
>>>>>>>>> since
>>>>>>>>> by default you need a field to store the component ref.
>>>>>>>>>
>>>>>>>>> not sure its worth doing it this way...
>>>>>>>>>
>>>>>>>>> -igor
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <
>>>>>>>>> mgrigorov@apache.org>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>  Hi,
>>>>>>>>>>
>>>>>>>>>> Recently Fridolin Jackstadt shared his approach to "autowire"
>>>>>>>>>> components
>>>>>>>>>>
>>>>>>>>>>  -
>>>>>>>>>
>>>>>>>>>  https://github.com/wicket-acc/wicket-autowire.
>>>>>>>>>>
>>>>>>>>>> I believe this approach can solve two issues:
>>>>>>>>>> - duplicate construction of the component tree - once in the
>>>>>>>>>> markup and
>>>>>>>>>> second time in Java code
>>>>>>>>>> - auto components available only in the render phase
>>>>>>>>>>
>>>>>>>>>> Here is how I see it:
>>>>>>>>>>
>>>>>>>>>> Any MarkupContainer that wants to use markup-driven-tree must
>>>>>>>>>> declare
>>>>>>>>>> the
>>>>>>>>>> components as member fields:
>>>>>>>>>>
>>>>>>>>>> private SomeComponent aComponent;
>>>>>>>>>>
>>>>>>>>>> These fields will be instantiated like any other component in
>>>>>>>>>> Wicket:
>>>>>>>>>>
>>>>>>>>>> aComponent = new SomeComponent(id, ...);
>>>>>>>>>>
>>>>>>>>>> The new thing is that they *won't* be added to a parent component
>>>>>>>>>> explicitly/manually.
>>>>>>>>>>
>>>>>>>>>> On Page#onInitialize() the first thing to do it to walk over the
>>>>>>>>>>
>>>>>>>>>>  component
>>>>>>>>>
>>>>>>>>>  tree from the page's markup (just like the walk in the rendering
>>>>>>>>>> related
>>>>>>>>>> code) and resolve the missing bits.
>>>>>>>>>> I.e. while walking thru the markup tree we will check the Java
>>>>>>>>>> component
>>>>>>>>>> tree (container.get(tagId)). If there is a miss then we search
>>>>>>>>>> for a
>>>>>>>>>>
>>>>>>>>>>  member
>>>>>>>>>
>>>>>>>>>  field that is a component with the same id in the current
>>>>>>>>>>
>>>>>>>>>>  MarkupContainer,
>>>>>>>>>
>>>>>>>>>  its (Java) super classes and finally in its (Wicket) parent
>>>>>>>>>> classes.
>>>>>>>>>>
>>>>>>>>>> This will solve issue #1 (identical trees in Java and markup)
>>>>>>>>>> (P.S. Fridolin's code uses @AutoComponent annotation that
>>>>>>>>>> facilitates
>>>>>>>>>> searching by component id, but will duplicate the declaration of
>>>>>>>>>> the id
>>>>>>>>>> -
>>>>>>>>>> once in the annotation and second time in 'new MyComponent(ID).
>>>>>>>>>> This is
>>>>>>>>>>
>>>>>>>>>>  an
>>>>>>>>>
>>>>>>>>>  implementation detail.)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> The second part is not less hard - during the walk over the
>>>>>>>>>> markup tree
>>>>>>>>>> when an autocomponent (e.g. enclosure) is seen Wicket will use the
>>>>>>>>>> registered IComponentResolvers to create the Java component and
>>>>>>>>>> insert
>>>>>>>>>> it
>>>>>>>>>> in the Java tree.
>>>>>>>>>> The tricky part here is that any manually added components (like
>>>>>>>>>> in
>>>>>>>>>>
>>>>>>>>>>  Wicket
>>>>>>>>>
>>>>>>>>>  6.x) to the parent of the autocomponent should be moved into the
>>>>>>>>>> autocomponent.
>>>>>>>>>> For example:
>>>>>>>>>>
>>>>>>>>>> <div wicket:id="a">
>>>>>>>>>>      <wicket:enclosure child="b">
>>>>>>>>>>         <span wicket:id="b"></span>
>>>>>>>>>>         <span wicket:id="c"></span>
>>>>>>>>>>      </wicket:enclosure>
>>>>>>>>>> </div>
>>>>>>>>>>
>>>>>>>>>> If 'b' and 'c' are added manually to 'a' in the application's
>>>>>>>>>> Java code:
>>>>>>>>>> (a (b,c))
>>>>>>>>>>
>>>>>>>>>> then after the "resolving phase" the tree will be:
>>>>>>>>>>
>>>>>>>>>> a (enclosure(b, c))
>>>>>>>>>>
>>>>>>>>>> so b.getParent() in onInitialize() and later will return the
>>>>>>>>>> Enclosure,
>>>>>>>>>>
>>>>>>>>>>  not
>>>>>>>>>
>>>>>>>>>  'a'.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> I don't know very well the MarkupStream APIs but I think all this
>>>>>>>>>> should
>>>>>>>>>>
>>>>>>>>>>  be
>>>>>>>>>
>>>>>>>>>  possible.
>>>>>>>>>>
>>>>>>>>>> WDYT about this approach ?
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Martin Grigorov
>>>>>>>>>> Wicket Training and Consulting
>>>>>>>>>>
>>>>>>>>>>
>>>>>
>>>>
>>>
>>
>

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
Reading the archives for Igor's work on "component queueing" I see

Igor Vaynberg<https://issues.apache.org/jira/secure/ViewProfile.jspa?name=ivaynberg>
added
a comment - 09/Jul/11 23:39

@Juergen, right now your tests only test for rendering, but they should
also test that before queued component's oninitialize is called the
component is already a child of the correct parent.

https://issues.apache.org/jira/browse/WICKET-3335


This means that
org.apache.wicket.application.IComponentInitializationListener cannot be
used. The tree (re)building should happen *before *components'
#onInitialize() and .IComponentInitializationListener#onInitialize() is
called *after*.

Martin Grigorov
Wicket Training and Consulting


On Fri, Jan 24, 2014 at 2:22 PM, Martin Grigorov <mg...@apache.org>wrote:

> I've added alternative ways to use MarkupDrivenComponentTreeBuilder:
> - with org.apache.wicket.MarkupDrivenTreeInitializionListener
> - with org.apache.wicket.MarkupDrivenComponentTreeBehavior#onConfigure
>
> Both of them do not check the configuration setting whether markup driven
> tree construction is enabled for now.
>
> The approach with MarkupDrivenTreeInitializionListener works the same way
> as the "inlined" version. The component tree rebuild is activated *after*
> all Component#onInitialize().
>
> The approach with MarkupDrivenComponentTreeBehavior uses #onConfigure().
> Here I had to change Enclosure class - the child component resolving should
> be done as late as possible just before the rendering phase starts.
>
> Martin Grigorov
> Wicket Training and Consulting
>
>
> On Fri, Jan 24, 2014 at 11:47 AM, Martin Grigorov <mg...@apache.org>wrote:
>
>> OK, the new impl is committed.
>> Now MarkupContainer has #enqueue(Component...) method that adds
>> components into a list.
>> Later org.apache.wicket.ComponentTreeBuilder#rebuild() uses the list, and
>> finally the list is null-yfied in #onDetach() so it is not serialized and
>> not available for the next requests. I guess the null-yfing can be done
>> earlier so even the first request have the extra bytes after the rebuild of
>> the tree.
>>
>> No need of @Auto anymore.
>>
>> Martin Grigorov
>> Wicket Training and Consulting
>>
>>
>> On Fri, Jan 24, 2014 at 10:39 AM, Martin Grigorov <mg...@apache.org>wrote:
>>
>>>
>>>
>>> On Fri, Jan 24, 2014 at 9:48 AM, Sven Meier <sv...@meiers.net> wrote:
>>>
>>>> > per-component basis - yes, as I explained earlier this is possible
>>>> with the current impl
>>>>
>>>> I must have missed that. Is there an example in the branch?
>>>>
>>>
>>> See
>>> https://github.com/apache/wicket/blob/markup-driven-component-tree/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java?source=c#L1886
>>> There is no test yet.
>>>
>>>
>>>>
>>>> I don't understand why there's need for an @Auto annotation. Why would
>>>> some components be annotated and some not?
>>>
>>>
>>> The annotation was needed to be able to find the component faster.
>>> I.e. check only annotated fields. If @Auto(id=...) then use the id to
>>> match against the component tag id.
>>>
>>> But with my new idea, the one that will solve the issue with the extra
>>> bytes, this won't be needed anymore.
>>> Stay tuned.
>>>
>>>
>>>>
>>>>
>>>>  behaviors don't have hooks for onInitialize()
>>>>>
>>>>
>>>> It could be done in #onConfigue(), that's early enough.
>>>
>>>
>>> The problem is that it is called for each request.
>>> For now I think there is no need to rebuild the component tree for each
>>> request, so we will have to use a guard (e.g. boolean field in the
>>> component).
>>> I will consider it.
>>>
>>>
>>>>
>>>>
>>>>  Additionally I think using Behavior will add a bit more bytes to each
>>>>> component than the current solution
>>>>>
>>>>
>>>> I don't think that is a problem: IMHO it's important to make this
>>>> feature optional, so when users don't use it then they do not pay a price.
>>>>
>>>> Regards
>>>> Sven
>>>>
>>>>
>>>>
>>>>
>>>> On 01/24/2014 06:35 AM, Martin Grigorov wrote:
>>>>
>>>>> On Fri, Jan 24, 2014 at 12:04 AM, Sven Meier <sv...@meiers.net> wrote:
>>>>>
>>>>>  Hi,
>>>>>>
>>>>>> I don't think we're heading the right direction with this and I
>>>>>> wouldn't
>>>>>> advertise it as anything yet.
>>>>>>
>>>>>>  I'd like to advertise it anyhow now just to have more people feeding
>>>>> me
>>>>> with stoppers, as you and Igor do. Thanks! :-)
>>>>>
>>>>>
>>>>>  There are more questions to come but here is one upfront:
>>>>>>
>>>>>>
>>>>>>  And it is configurable, by default disabled.
>>>>>>>
>>>>>> As Igor has written, this does not work with component libraries which
>>>>>> depend on the new feature.
>>>>>> Couldn't this feature be enabled/disabled on a per-component basis?
>>>>>> Why
>>>>>> not make it a behavior that you can attach to components if you want
>>>>>> to use
>>>>>> automatic resolving/rearranging of its children?
>>>>>>
>>>>>>  - per-component basis - yes, as I explained earlier this is possible
>>>>> with
>>>>> the current impl
>>>>> - behaviors don't have hooks for onInitialize()
>>>>> After Igor's feedback I think onAfterInitialize() is what is needed, so
>>>>> apps can use onInitialize() as a complement to the constructor
>>>>> Additionally I think using Behavior will add a bit more bytes to each
>>>>> component than the current solution
>>>>>
>>>>>
>>>>>  Regards
>>>>>> Sven
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 01/23/2014 05:20 PM, Martin Grigorov wrote:
>>>>>>
>>>>>>  Once the markup driven construction is done (just before
>>>>>>> onInitialize())
>>>>>>> the application will have to use the old good add()/addOrReplace().
>>>>>>>
>>>>>>> The components are already in the MarkupContainer#children data
>>>>>>> structure.
>>>>>>> So each field will add extra 8 bytes on 64bit machine (or 4 bytes
>>>>>>> with
>>>>>>> CompressedOops enabled).
>>>>>>> Serialization is the same - the object is written once, with several
>>>>>>> pointers.
>>>>>>>
>>>>>>> I am also not fully sure in the approach but I am experimenting and
>>>>>>> so far
>>>>>>> it works well.
>>>>>>> And it is configurable, by default disabled.
>>>>>>> We can advertise it as experimental ?!
>>>>>>>
>>>>>>> I will add more use cases/tests soon.
>>>>>>> And caching for the reflection stuff.
>>>>>>>
>>>>>>>
>>>>>>> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <
>>>>>>> igor.vaynberg@gmail.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>   what about components added in onInitialize() or on onConfigure()?
>>>>>>>
>>>>>>>> this will also lead to a higher memory/serialization space usage
>>>>>>>> since
>>>>>>>> by default you need a field to store the component ref.
>>>>>>>>
>>>>>>>> not sure its worth doing it this way...
>>>>>>>>
>>>>>>>> -igor
>>>>>>>>
>>>>>>>>
>>>>>>>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <
>>>>>>>> mgrigorov@apache.org>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>  Hi,
>>>>>>>>>
>>>>>>>>> Recently Fridolin Jackstadt shared his approach to "autowire"
>>>>>>>>> components
>>>>>>>>>
>>>>>>>>>  -
>>>>>>>>
>>>>>>>>  https://github.com/wicket-acc/wicket-autowire.
>>>>>>>>>
>>>>>>>>> I believe this approach can solve two issues:
>>>>>>>>> - duplicate construction of the component tree - once in the
>>>>>>>>> markup and
>>>>>>>>> second time in Java code
>>>>>>>>> - auto components available only in the render phase
>>>>>>>>>
>>>>>>>>> Here is how I see it:
>>>>>>>>>
>>>>>>>>> Any MarkupContainer that wants to use markup-driven-tree must
>>>>>>>>> declare
>>>>>>>>> the
>>>>>>>>> components as member fields:
>>>>>>>>>
>>>>>>>>> private SomeComponent aComponent;
>>>>>>>>>
>>>>>>>>> These fields will be instantiated like any other component in
>>>>>>>>> Wicket:
>>>>>>>>>
>>>>>>>>> aComponent = new SomeComponent(id, ...);
>>>>>>>>>
>>>>>>>>> The new thing is that they *won't* be added to a parent component
>>>>>>>>> explicitly/manually.
>>>>>>>>>
>>>>>>>>> On Page#onInitialize() the first thing to do it to walk over the
>>>>>>>>>
>>>>>>>>>  component
>>>>>>>>
>>>>>>>>  tree from the page's markup (just like the walk in the rendering
>>>>>>>>> related
>>>>>>>>> code) and resolve the missing bits.
>>>>>>>>> I.e. while walking thru the markup tree we will check the Java
>>>>>>>>> component
>>>>>>>>> tree (container.get(tagId)). If there is a miss then we search for
>>>>>>>>> a
>>>>>>>>>
>>>>>>>>>  member
>>>>>>>>
>>>>>>>>  field that is a component with the same id in the current
>>>>>>>>>
>>>>>>>>>  MarkupContainer,
>>>>>>>>
>>>>>>>>  its (Java) super classes and finally in its (Wicket) parent
>>>>>>>>> classes.
>>>>>>>>>
>>>>>>>>> This will solve issue #1 (identical trees in Java and markup)
>>>>>>>>> (P.S. Fridolin's code uses @AutoComponent annotation that
>>>>>>>>> facilitates
>>>>>>>>> searching by component id, but will duplicate the declaration of
>>>>>>>>> the id
>>>>>>>>> -
>>>>>>>>> once in the annotation and second time in 'new MyComponent(ID).
>>>>>>>>> This is
>>>>>>>>>
>>>>>>>>>  an
>>>>>>>>
>>>>>>>>  implementation detail.)
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The second part is not less hard - during the walk over the markup
>>>>>>>>> tree
>>>>>>>>> when an autocomponent (e.g. enclosure) is seen Wicket will use the
>>>>>>>>> registered IComponentResolvers to create the Java component and
>>>>>>>>> insert
>>>>>>>>> it
>>>>>>>>> in the Java tree.
>>>>>>>>> The tricky part here is that any manually added components (like in
>>>>>>>>>
>>>>>>>>>  Wicket
>>>>>>>>
>>>>>>>>  6.x) to the parent of the autocomponent should be moved into the
>>>>>>>>> autocomponent.
>>>>>>>>> For example:
>>>>>>>>>
>>>>>>>>> <div wicket:id="a">
>>>>>>>>>      <wicket:enclosure child="b">
>>>>>>>>>         <span wicket:id="b"></span>
>>>>>>>>>         <span wicket:id="c"></span>
>>>>>>>>>      </wicket:enclosure>
>>>>>>>>> </div>
>>>>>>>>>
>>>>>>>>> If 'b' and 'c' are added manually to 'a' in the application's Java
>>>>>>>>> code:
>>>>>>>>> (a (b,c))
>>>>>>>>>
>>>>>>>>> then after the "resolving phase" the tree will be:
>>>>>>>>>
>>>>>>>>> a (enclosure(b, c))
>>>>>>>>>
>>>>>>>>> so b.getParent() in onInitialize() and later will return the
>>>>>>>>> Enclosure,
>>>>>>>>>
>>>>>>>>>  not
>>>>>>>>
>>>>>>>>  'a'.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> I don't know very well the MarkupStream APIs but I think all this
>>>>>>>>> should
>>>>>>>>>
>>>>>>>>>  be
>>>>>>>>
>>>>>>>>  possible.
>>>>>>>>>
>>>>>>>>> WDYT about this approach ?
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Martin Grigorov
>>>>>>>>> Wicket Training and Consulting
>>>>>>>>>
>>>>>>>>>
>>>>
>>>
>>
>

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
I've added alternative ways to use MarkupDrivenComponentTreeBuilder:
- with org.apache.wicket.MarkupDrivenTreeInitializionListener
- with org.apache.wicket.MarkupDrivenComponentTreeBehavior#onConfigure

Both of them do not check the configuration setting whether markup driven
tree construction is enabled for now.

The approach with MarkupDrivenTreeInitializionListener works the same way
as the "inlined" version. The component tree rebuild is activated *after*
all Component#onInitialize().

The approach with MarkupDrivenComponentTreeBehavior uses #onConfigure().
Here I had to change Enclosure class - the child component resolving should
be done as late as possible just before the rendering phase starts.

Martin Grigorov
Wicket Training and Consulting


On Fri, Jan 24, 2014 at 11:47 AM, Martin Grigorov <mg...@apache.org>wrote:

> OK, the new impl is committed.
> Now MarkupContainer has #enqueue(Component...) method that adds components
> into a list.
> Later org.apache.wicket.ComponentTreeBuilder#rebuild() uses the list, and
> finally the list is null-yfied in #onDetach() so it is not serialized and
> not available for the next requests. I guess the null-yfing can be done
> earlier so even the first request have the extra bytes after the rebuild of
> the tree.
>
> No need of @Auto anymore.
>
> Martin Grigorov
> Wicket Training and Consulting
>
>
> On Fri, Jan 24, 2014 at 10:39 AM, Martin Grigorov <mg...@apache.org>wrote:
>
>>
>>
>> On Fri, Jan 24, 2014 at 9:48 AM, Sven Meier <sv...@meiers.net> wrote:
>>
>>> > per-component basis - yes, as I explained earlier this is possible
>>> with the current impl
>>>
>>> I must have missed that. Is there an example in the branch?
>>>
>>
>> See
>> https://github.com/apache/wicket/blob/markup-driven-component-tree/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java?source=c#L1886
>> There is no test yet.
>>
>>
>>>
>>> I don't understand why there's need for an @Auto annotation. Why would
>>> some components be annotated and some not?
>>
>>
>> The annotation was needed to be able to find the component faster.
>> I.e. check only annotated fields. If @Auto(id=...) then use the id to
>> match against the component tag id.
>>
>> But with my new idea, the one that will solve the issue with the extra
>> bytes, this won't be needed anymore.
>> Stay tuned.
>>
>>
>>>
>>>
>>>  behaviors don't have hooks for onInitialize()
>>>>
>>>
>>> It could be done in #onConfigue(), that's early enough.
>>
>>
>> The problem is that it is called for each request.
>> For now I think there is no need to rebuild the component tree for each
>> request, so we will have to use a guard (e.g. boolean field in the
>> component).
>> I will consider it.
>>
>>
>>>
>>>
>>>  Additionally I think using Behavior will add a bit more bytes to each
>>>> component than the current solution
>>>>
>>>
>>> I don't think that is a problem: IMHO it's important to make this
>>> feature optional, so when users don't use it then they do not pay a price.
>>>
>>> Regards
>>> Sven
>>>
>>>
>>>
>>>
>>> On 01/24/2014 06:35 AM, Martin Grigorov wrote:
>>>
>>>> On Fri, Jan 24, 2014 at 12:04 AM, Sven Meier <sv...@meiers.net> wrote:
>>>>
>>>>  Hi,
>>>>>
>>>>> I don't think we're heading the right direction with this and I
>>>>> wouldn't
>>>>> advertise it as anything yet.
>>>>>
>>>>>  I'd like to advertise it anyhow now just to have more people feeding
>>>> me
>>>> with stoppers, as you and Igor do. Thanks! :-)
>>>>
>>>>
>>>>  There are more questions to come but here is one upfront:
>>>>>
>>>>>
>>>>>  And it is configurable, by default disabled.
>>>>>>
>>>>> As Igor has written, this does not work with component libraries which
>>>>> depend on the new feature.
>>>>> Couldn't this feature be enabled/disabled on a per-component basis? Why
>>>>> not make it a behavior that you can attach to components if you want
>>>>> to use
>>>>> automatic resolving/rearranging of its children?
>>>>>
>>>>>  - per-component basis - yes, as I explained earlier this is possible
>>>> with
>>>> the current impl
>>>> - behaviors don't have hooks for onInitialize()
>>>> After Igor's feedback I think onAfterInitialize() is what is needed, so
>>>> apps can use onInitialize() as a complement to the constructor
>>>> Additionally I think using Behavior will add a bit more bytes to each
>>>> component than the current solution
>>>>
>>>>
>>>>  Regards
>>>>> Sven
>>>>>
>>>>>
>>>>>
>>>>> On 01/23/2014 05:20 PM, Martin Grigorov wrote:
>>>>>
>>>>>  Once the markup driven construction is done (just before
>>>>>> onInitialize())
>>>>>> the application will have to use the old good add()/addOrReplace().
>>>>>>
>>>>>> The components are already in the MarkupContainer#children data
>>>>>> structure.
>>>>>> So each field will add extra 8 bytes on 64bit machine (or 4 bytes with
>>>>>> CompressedOops enabled).
>>>>>> Serialization is the same - the object is written once, with several
>>>>>> pointers.
>>>>>>
>>>>>> I am also not fully sure in the approach but I am experimenting and
>>>>>> so far
>>>>>> it works well.
>>>>>> And it is configurable, by default disabled.
>>>>>> We can advertise it as experimental ?!
>>>>>>
>>>>>> I will add more use cases/tests soon.
>>>>>> And caching for the reflection stuff.
>>>>>>
>>>>>>
>>>>>> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <
>>>>>> igor.vaynberg@gmail.com>
>>>>>> wrote:
>>>>>>
>>>>>>   what about components added in onInitialize() or on onConfigure()?
>>>>>>
>>>>>>> this will also lead to a higher memory/serialization space usage
>>>>>>> since
>>>>>>> by default you need a field to store the component ref.
>>>>>>>
>>>>>>> not sure its worth doing it this way...
>>>>>>>
>>>>>>> -igor
>>>>>>>
>>>>>>>
>>>>>>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <
>>>>>>> mgrigorov@apache.org>
>>>>>>> wrote:
>>>>>>>
>>>>>>>  Hi,
>>>>>>>>
>>>>>>>> Recently Fridolin Jackstadt shared his approach to "autowire"
>>>>>>>> components
>>>>>>>>
>>>>>>>>  -
>>>>>>>
>>>>>>>  https://github.com/wicket-acc/wicket-autowire.
>>>>>>>>
>>>>>>>> I believe this approach can solve two issues:
>>>>>>>> - duplicate construction of the component tree - once in the markup
>>>>>>>> and
>>>>>>>> second time in Java code
>>>>>>>> - auto components available only in the render phase
>>>>>>>>
>>>>>>>> Here is how I see it:
>>>>>>>>
>>>>>>>> Any MarkupContainer that wants to use markup-driven-tree must
>>>>>>>> declare
>>>>>>>> the
>>>>>>>> components as member fields:
>>>>>>>>
>>>>>>>> private SomeComponent aComponent;
>>>>>>>>
>>>>>>>> These fields will be instantiated like any other component in
>>>>>>>> Wicket:
>>>>>>>>
>>>>>>>> aComponent = new SomeComponent(id, ...);
>>>>>>>>
>>>>>>>> The new thing is that they *won't* be added to a parent component
>>>>>>>> explicitly/manually.
>>>>>>>>
>>>>>>>> On Page#onInitialize() the first thing to do it to walk over the
>>>>>>>>
>>>>>>>>  component
>>>>>>>
>>>>>>>  tree from the page's markup (just like the walk in the rendering
>>>>>>>> related
>>>>>>>> code) and resolve the missing bits.
>>>>>>>> I.e. while walking thru the markup tree we will check the Java
>>>>>>>> component
>>>>>>>> tree (container.get(tagId)). If there is a miss then we search for a
>>>>>>>>
>>>>>>>>  member
>>>>>>>
>>>>>>>  field that is a component with the same id in the current
>>>>>>>>
>>>>>>>>  MarkupContainer,
>>>>>>>
>>>>>>>  its (Java) super classes and finally in its (Wicket) parent classes.
>>>>>>>>
>>>>>>>> This will solve issue #1 (identical trees in Java and markup)
>>>>>>>> (P.S. Fridolin's code uses @AutoComponent annotation that
>>>>>>>> facilitates
>>>>>>>> searching by component id, but will duplicate the declaration of
>>>>>>>> the id
>>>>>>>> -
>>>>>>>> once in the annotation and second time in 'new MyComponent(ID).
>>>>>>>> This is
>>>>>>>>
>>>>>>>>  an
>>>>>>>
>>>>>>>  implementation detail.)
>>>>>>>>
>>>>>>>>
>>>>>>>> The second part is not less hard - during the walk over the markup
>>>>>>>> tree
>>>>>>>> when an autocomponent (e.g. enclosure) is seen Wicket will use the
>>>>>>>> registered IComponentResolvers to create the Java component and
>>>>>>>> insert
>>>>>>>> it
>>>>>>>> in the Java tree.
>>>>>>>> The tricky part here is that any manually added components (like in
>>>>>>>>
>>>>>>>>  Wicket
>>>>>>>
>>>>>>>  6.x) to the parent of the autocomponent should be moved into the
>>>>>>>> autocomponent.
>>>>>>>> For example:
>>>>>>>>
>>>>>>>> <div wicket:id="a">
>>>>>>>>      <wicket:enclosure child="b">
>>>>>>>>         <span wicket:id="b"></span>
>>>>>>>>         <span wicket:id="c"></span>
>>>>>>>>      </wicket:enclosure>
>>>>>>>> </div>
>>>>>>>>
>>>>>>>> If 'b' and 'c' are added manually to 'a' in the application's Java
>>>>>>>> code:
>>>>>>>> (a (b,c))
>>>>>>>>
>>>>>>>> then after the "resolving phase" the tree will be:
>>>>>>>>
>>>>>>>> a (enclosure(b, c))
>>>>>>>>
>>>>>>>> so b.getParent() in onInitialize() and later will return the
>>>>>>>> Enclosure,
>>>>>>>>
>>>>>>>>  not
>>>>>>>
>>>>>>>  'a'.
>>>>>>>>
>>>>>>>>
>>>>>>>> I don't know very well the MarkupStream APIs but I think all this
>>>>>>>> should
>>>>>>>>
>>>>>>>>  be
>>>>>>>
>>>>>>>  possible.
>>>>>>>>
>>>>>>>> WDYT about this approach ?
>>>>>>>>
>>>>>>>>
>>>>>>>> Martin Grigorov
>>>>>>>> Wicket Training and Consulting
>>>>>>>>
>>>>>>>>
>>>
>>
>

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
OK, the new impl is committed.
Now MarkupContainer has #enqueue(Component...) method that adds components
into a list.
Later org.apache.wicket.ComponentTreeBuilder#rebuild() uses the list, and
finally the list is null-yfied in #onDetach() so it is not serialized and
not available for the next requests. I guess the null-yfing can be done
earlier so even the first request have the extra bytes after the rebuild of
the tree.

No need of @Auto anymore.

Martin Grigorov
Wicket Training and Consulting


On Fri, Jan 24, 2014 at 10:39 AM, Martin Grigorov <mg...@apache.org>wrote:

>
>
> On Fri, Jan 24, 2014 at 9:48 AM, Sven Meier <sv...@meiers.net> wrote:
>
>> > per-component basis - yes, as I explained earlier this is possible with
>> the current impl
>>
>> I must have missed that. Is there an example in the branch?
>>
>
> See
> https://github.com/apache/wicket/blob/markup-driven-component-tree/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java?source=c#L1886
> There is no test yet.
>
>
>>
>> I don't understand why there's need for an @Auto annotation. Why would
>> some components be annotated and some not?
>
>
> The annotation was needed to be able to find the component faster.
> I.e. check only annotated fields. If @Auto(id=...) then use the id to
> match against the component tag id.
>
> But with my new idea, the one that will solve the issue with the extra
> bytes, this won't be needed anymore.
> Stay tuned.
>
>
>>
>>
>>  behaviors don't have hooks for onInitialize()
>>>
>>
>> It could be done in #onConfigue(), that's early enough.
>
>
> The problem is that it is called for each request.
> For now I think there is no need to rebuild the component tree for each
> request, so we will have to use a guard (e.g. boolean field in the
> component).
> I will consider it.
>
>
>>
>>
>>  Additionally I think using Behavior will add a bit more bytes to each
>>> component than the current solution
>>>
>>
>> I don't think that is a problem: IMHO it's important to make this feature
>> optional, so when users don't use it then they do not pay a price.
>>
>> Regards
>> Sven
>>
>>
>>
>>
>> On 01/24/2014 06:35 AM, Martin Grigorov wrote:
>>
>>> On Fri, Jan 24, 2014 at 12:04 AM, Sven Meier <sv...@meiers.net> wrote:
>>>
>>>  Hi,
>>>>
>>>> I don't think we're heading the right direction with this and I wouldn't
>>>> advertise it as anything yet.
>>>>
>>>>  I'd like to advertise it anyhow now just to have more people feeding me
>>> with stoppers, as you and Igor do. Thanks! :-)
>>>
>>>
>>>  There are more questions to come but here is one upfront:
>>>>
>>>>
>>>>  And it is configurable, by default disabled.
>>>>>
>>>> As Igor has written, this does not work with component libraries which
>>>> depend on the new feature.
>>>> Couldn't this feature be enabled/disabled on a per-component basis? Why
>>>> not make it a behavior that you can attach to components if you want to
>>>> use
>>>> automatic resolving/rearranging of its children?
>>>>
>>>>  - per-component basis - yes, as I explained earlier this is possible
>>> with
>>> the current impl
>>> - behaviors don't have hooks for onInitialize()
>>> After Igor's feedback I think onAfterInitialize() is what is needed, so
>>> apps can use onInitialize() as a complement to the constructor
>>> Additionally I think using Behavior will add a bit more bytes to each
>>> component than the current solution
>>>
>>>
>>>  Regards
>>>> Sven
>>>>
>>>>
>>>>
>>>> On 01/23/2014 05:20 PM, Martin Grigorov wrote:
>>>>
>>>>  Once the markup driven construction is done (just before
>>>>> onInitialize())
>>>>> the application will have to use the old good add()/addOrReplace().
>>>>>
>>>>> The components are already in the MarkupContainer#children data
>>>>> structure.
>>>>> So each field will add extra 8 bytes on 64bit machine (or 4 bytes with
>>>>> CompressedOops enabled).
>>>>> Serialization is the same - the object is written once, with several
>>>>> pointers.
>>>>>
>>>>> I am also not fully sure in the approach but I am experimenting and so
>>>>> far
>>>>> it works well.
>>>>> And it is configurable, by default disabled.
>>>>> We can advertise it as experimental ?!
>>>>>
>>>>> I will add more use cases/tests soon.
>>>>> And caching for the reflection stuff.
>>>>>
>>>>>
>>>>> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <
>>>>> igor.vaynberg@gmail.com>
>>>>> wrote:
>>>>>
>>>>>   what about components added in onInitialize() or on onConfigure()?
>>>>>
>>>>>> this will also lead to a higher memory/serialization space usage since
>>>>>> by default you need a field to store the component ref.
>>>>>>
>>>>>> not sure its worth doing it this way...
>>>>>>
>>>>>> -igor
>>>>>>
>>>>>>
>>>>>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <
>>>>>> mgrigorov@apache.org>
>>>>>> wrote:
>>>>>>
>>>>>>  Hi,
>>>>>>>
>>>>>>> Recently Fridolin Jackstadt shared his approach to "autowire"
>>>>>>> components
>>>>>>>
>>>>>>>  -
>>>>>>
>>>>>>  https://github.com/wicket-acc/wicket-autowire.
>>>>>>>
>>>>>>> I believe this approach can solve two issues:
>>>>>>> - duplicate construction of the component tree - once in the markup
>>>>>>> and
>>>>>>> second time in Java code
>>>>>>> - auto components available only in the render phase
>>>>>>>
>>>>>>> Here is how I see it:
>>>>>>>
>>>>>>> Any MarkupContainer that wants to use markup-driven-tree must declare
>>>>>>> the
>>>>>>> components as member fields:
>>>>>>>
>>>>>>> private SomeComponent aComponent;
>>>>>>>
>>>>>>> These fields will be instantiated like any other component in Wicket:
>>>>>>>
>>>>>>> aComponent = new SomeComponent(id, ...);
>>>>>>>
>>>>>>> The new thing is that they *won't* be added to a parent component
>>>>>>> explicitly/manually.
>>>>>>>
>>>>>>> On Page#onInitialize() the first thing to do it to walk over the
>>>>>>>
>>>>>>>  component
>>>>>>
>>>>>>  tree from the page's markup (just like the walk in the rendering
>>>>>>> related
>>>>>>> code) and resolve the missing bits.
>>>>>>> I.e. while walking thru the markup tree we will check the Java
>>>>>>> component
>>>>>>> tree (container.get(tagId)). If there is a miss then we search for a
>>>>>>>
>>>>>>>  member
>>>>>>
>>>>>>  field that is a component with the same id in the current
>>>>>>>
>>>>>>>  MarkupContainer,
>>>>>>
>>>>>>  its (Java) super classes and finally in its (Wicket) parent classes.
>>>>>>>
>>>>>>> This will solve issue #1 (identical trees in Java and markup)
>>>>>>> (P.S. Fridolin's code uses @AutoComponent annotation that facilitates
>>>>>>> searching by component id, but will duplicate the declaration of the
>>>>>>> id
>>>>>>> -
>>>>>>> once in the annotation and second time in 'new MyComponent(ID). This
>>>>>>> is
>>>>>>>
>>>>>>>  an
>>>>>>
>>>>>>  implementation detail.)
>>>>>>>
>>>>>>>
>>>>>>> The second part is not less hard - during the walk over the markup
>>>>>>> tree
>>>>>>> when an autocomponent (e.g. enclosure) is seen Wicket will use the
>>>>>>> registered IComponentResolvers to create the Java component and
>>>>>>> insert
>>>>>>> it
>>>>>>> in the Java tree.
>>>>>>> The tricky part here is that any manually added components (like in
>>>>>>>
>>>>>>>  Wicket
>>>>>>
>>>>>>  6.x) to the parent of the autocomponent should be moved into the
>>>>>>> autocomponent.
>>>>>>> For example:
>>>>>>>
>>>>>>> <div wicket:id="a">
>>>>>>>      <wicket:enclosure child="b">
>>>>>>>         <span wicket:id="b"></span>
>>>>>>>         <span wicket:id="c"></span>
>>>>>>>      </wicket:enclosure>
>>>>>>> </div>
>>>>>>>
>>>>>>> If 'b' and 'c' are added manually to 'a' in the application's Java
>>>>>>> code:
>>>>>>> (a (b,c))
>>>>>>>
>>>>>>> then after the "resolving phase" the tree will be:
>>>>>>>
>>>>>>> a (enclosure(b, c))
>>>>>>>
>>>>>>> so b.getParent() in onInitialize() and later will return the
>>>>>>> Enclosure,
>>>>>>>
>>>>>>>  not
>>>>>>
>>>>>>  'a'.
>>>>>>>
>>>>>>>
>>>>>>> I don't know very well the MarkupStream APIs but I think all this
>>>>>>> should
>>>>>>>
>>>>>>>  be
>>>>>>
>>>>>>  possible.
>>>>>>>
>>>>>>> WDYT about this approach ?
>>>>>>>
>>>>>>>
>>>>>>> Martin Grigorov
>>>>>>> Wicket Training and Consulting
>>>>>>>
>>>>>>>
>>
>

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
On Fri, Jan 24, 2014 at 9:48 AM, Sven Meier <sv...@meiers.net> wrote:

> > per-component basis - yes, as I explained earlier this is possible with
> the current impl
>
> I must have missed that. Is there an example in the branch?
>

See
https://github.com/apache/wicket/blob/markup-driven-component-tree/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java?source=c#L1886
There is no test yet.


>
> I don't understand why there's need for an @Auto annotation. Why would
> some components be annotated and some not?


The annotation was needed to be able to find the component faster.
I.e. check only annotated fields. If @Auto(id=...) then use the id to match
against the component tag id.

But with my new idea, the one that will solve the issue with the extra
bytes, this won't be needed anymore.
Stay tuned.


>
>
>  behaviors don't have hooks for onInitialize()
>>
>
> It could be done in #onConfigue(), that's early enough.


The problem is that it is called for each request.
For now I think there is no need to rebuild the component tree for each
request, so we will have to use a guard (e.g. boolean field in the
component).
I will consider it.


>
>
>  Additionally I think using Behavior will add a bit more bytes to each
>> component than the current solution
>>
>
> I don't think that is a problem: IMHO it's important to make this feature
> optional, so when users don't use it then they do not pay a price.
>
> Regards
> Sven
>
>
>
>
> On 01/24/2014 06:35 AM, Martin Grigorov wrote:
>
>> On Fri, Jan 24, 2014 at 12:04 AM, Sven Meier <sv...@meiers.net> wrote:
>>
>>  Hi,
>>>
>>> I don't think we're heading the right direction with this and I wouldn't
>>> advertise it as anything yet.
>>>
>>>  I'd like to advertise it anyhow now just to have more people feeding me
>> with stoppers, as you and Igor do. Thanks! :-)
>>
>>
>>  There are more questions to come but here is one upfront:
>>>
>>>
>>>  And it is configurable, by default disabled.
>>>>
>>> As Igor has written, this does not work with component libraries which
>>> depend on the new feature.
>>> Couldn't this feature be enabled/disabled on a per-component basis? Why
>>> not make it a behavior that you can attach to components if you want to
>>> use
>>> automatic resolving/rearranging of its children?
>>>
>>>  - per-component basis - yes, as I explained earlier this is possible
>> with
>> the current impl
>> - behaviors don't have hooks for onInitialize()
>> After Igor's feedback I think onAfterInitialize() is what is needed, so
>> apps can use onInitialize() as a complement to the constructor
>> Additionally I think using Behavior will add a bit more bytes to each
>> component than the current solution
>>
>>
>>  Regards
>>> Sven
>>>
>>>
>>>
>>> On 01/23/2014 05:20 PM, Martin Grigorov wrote:
>>>
>>>  Once the markup driven construction is done (just before onInitialize())
>>>> the application will have to use the old good add()/addOrReplace().
>>>>
>>>> The components are already in the MarkupContainer#children data
>>>> structure.
>>>> So each field will add extra 8 bytes on 64bit machine (or 4 bytes with
>>>> CompressedOops enabled).
>>>> Serialization is the same - the object is written once, with several
>>>> pointers.
>>>>
>>>> I am also not fully sure in the approach but I am experimenting and so
>>>> far
>>>> it works well.
>>>> And it is configurable, by default disabled.
>>>> We can advertise it as experimental ?!
>>>>
>>>> I will add more use cases/tests soon.
>>>> And caching for the reflection stuff.
>>>>
>>>>
>>>> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <igor.vaynberg@gmail.com
>>>> >
>>>> wrote:
>>>>
>>>>   what about components added in onInitialize() or on onConfigure()?
>>>>
>>>>> this will also lead to a higher memory/serialization space usage since
>>>>> by default you need a field to store the component ref.
>>>>>
>>>>> not sure its worth doing it this way...
>>>>>
>>>>> -igor
>>>>>
>>>>>
>>>>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <
>>>>> mgrigorov@apache.org>
>>>>> wrote:
>>>>>
>>>>>  Hi,
>>>>>>
>>>>>> Recently Fridolin Jackstadt shared his approach to "autowire"
>>>>>> components
>>>>>>
>>>>>>  -
>>>>>
>>>>>  https://github.com/wicket-acc/wicket-autowire.
>>>>>>
>>>>>> I believe this approach can solve two issues:
>>>>>> - duplicate construction of the component tree - once in the markup
>>>>>> and
>>>>>> second time in Java code
>>>>>> - auto components available only in the render phase
>>>>>>
>>>>>> Here is how I see it:
>>>>>>
>>>>>> Any MarkupContainer that wants to use markup-driven-tree must declare
>>>>>> the
>>>>>> components as member fields:
>>>>>>
>>>>>> private SomeComponent aComponent;
>>>>>>
>>>>>> These fields will be instantiated like any other component in Wicket:
>>>>>>
>>>>>> aComponent = new SomeComponent(id, ...);
>>>>>>
>>>>>> The new thing is that they *won't* be added to a parent component
>>>>>> explicitly/manually.
>>>>>>
>>>>>> On Page#onInitialize() the first thing to do it to walk over the
>>>>>>
>>>>>>  component
>>>>>
>>>>>  tree from the page's markup (just like the walk in the rendering
>>>>>> related
>>>>>> code) and resolve the missing bits.
>>>>>> I.e. while walking thru the markup tree we will check the Java
>>>>>> component
>>>>>> tree (container.get(tagId)). If there is a miss then we search for a
>>>>>>
>>>>>>  member
>>>>>
>>>>>  field that is a component with the same id in the current
>>>>>>
>>>>>>  MarkupContainer,
>>>>>
>>>>>  its (Java) super classes and finally in its (Wicket) parent classes.
>>>>>>
>>>>>> This will solve issue #1 (identical trees in Java and markup)
>>>>>> (P.S. Fridolin's code uses @AutoComponent annotation that facilitates
>>>>>> searching by component id, but will duplicate the declaration of the
>>>>>> id
>>>>>> -
>>>>>> once in the annotation and second time in 'new MyComponent(ID). This
>>>>>> is
>>>>>>
>>>>>>  an
>>>>>
>>>>>  implementation detail.)
>>>>>>
>>>>>>
>>>>>> The second part is not less hard - during the walk over the markup
>>>>>> tree
>>>>>> when an autocomponent (e.g. enclosure) is seen Wicket will use the
>>>>>> registered IComponentResolvers to create the Java component and insert
>>>>>> it
>>>>>> in the Java tree.
>>>>>> The tricky part here is that any manually added components (like in
>>>>>>
>>>>>>  Wicket
>>>>>
>>>>>  6.x) to the parent of the autocomponent should be moved into the
>>>>>> autocomponent.
>>>>>> For example:
>>>>>>
>>>>>> <div wicket:id="a">
>>>>>>      <wicket:enclosure child="b">
>>>>>>         <span wicket:id="b"></span>
>>>>>>         <span wicket:id="c"></span>
>>>>>>      </wicket:enclosure>
>>>>>> </div>
>>>>>>
>>>>>> If 'b' and 'c' are added manually to 'a' in the application's Java
>>>>>> code:
>>>>>> (a (b,c))
>>>>>>
>>>>>> then after the "resolving phase" the tree will be:
>>>>>>
>>>>>> a (enclosure(b, c))
>>>>>>
>>>>>> so b.getParent() in onInitialize() and later will return the
>>>>>> Enclosure,
>>>>>>
>>>>>>  not
>>>>>
>>>>>  'a'.
>>>>>>
>>>>>>
>>>>>> I don't know very well the MarkupStream APIs but I think all this
>>>>>> should
>>>>>>
>>>>>>  be
>>>>>
>>>>>  possible.
>>>>>>
>>>>>> WDYT about this approach ?
>>>>>>
>>>>>>
>>>>>> Martin Grigorov
>>>>>> Wicket Training and Consulting
>>>>>>
>>>>>>
>

Re: Markup driven component tree

Posted by Sven Meier <sv...@meiers.net>.
 > per-component basis - yes, as I explained earlier this is possible 
with the current impl

I must have missed that. Is there an example in the branch?

I don't understand why there's need for an @Auto annotation. Why would 
some components be annotated and some not?

> behaviors don't have hooks for onInitialize()

It could be done in #onConfigue(), that's early enough.

>Additionally I think using Behavior will add a bit more bytes to each
>component than the current solution

I don't think that is a problem: IMHO it's important to make this feature optional, so when users don't use it then they do not pay a price.

Regards
Sven



On 01/24/2014 06:35 AM, Martin Grigorov wrote:
> On Fri, Jan 24, 2014 at 12:04 AM, Sven Meier <sv...@meiers.net> wrote:
>
>> Hi,
>>
>> I don't think we're heading the right direction with this and I wouldn't
>> advertise it as anything yet.
>>
> I'd like to advertise it anyhow now just to have more people feeding me
> with stoppers, as you and Igor do. Thanks! :-)
>
>
>> There are more questions to come but here is one upfront:
>>
>>
>>> And it is configurable, by default disabled.
>> As Igor has written, this does not work with component libraries which
>> depend on the new feature.
>> Couldn't this feature be enabled/disabled on a per-component basis? Why
>> not make it a behavior that you can attach to components if you want to use
>> automatic resolving/rearranging of its children?
>>
> - per-component basis - yes, as I explained earlier this is possible with
> the current impl
> - behaviors don't have hooks for onInitialize()
> After Igor's feedback I think onAfterInitialize() is what is needed, so
> apps can use onInitialize() as a complement to the constructor
> Additionally I think using Behavior will add a bit more bytes to each
> component than the current solution
>
>
>> Regards
>> Sven
>>
>>
>>
>> On 01/23/2014 05:20 PM, Martin Grigorov wrote:
>>
>>> Once the markup driven construction is done (just before onInitialize())
>>> the application will have to use the old good add()/addOrReplace().
>>>
>>> The components are already in the MarkupContainer#children data structure.
>>> So each field will add extra 8 bytes on 64bit machine (or 4 bytes with
>>> CompressedOops enabled).
>>> Serialization is the same - the object is written once, with several
>>> pointers.
>>>
>>> I am also not fully sure in the approach but I am experimenting and so far
>>> it works well.
>>> And it is configurable, by default disabled.
>>> We can advertise it as experimental ?!
>>>
>>> I will add more use cases/tests soon.
>>> And caching for the reflection stuff.
>>>
>>>
>>> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <ig...@gmail.com>
>>> wrote:
>>>
>>>   what about components added in onInitialize() or on onConfigure()?
>>>> this will also lead to a higher memory/serialization space usage since
>>>> by default you need a field to store the component ref.
>>>>
>>>> not sure its worth doing it this way...
>>>>
>>>> -igor
>>>>
>>>>
>>>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <mg...@apache.org>
>>>> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> Recently Fridolin Jackstadt shared his approach to "autowire" components
>>>>>
>>>> -
>>>>
>>>>> https://github.com/wicket-acc/wicket-autowire.
>>>>>
>>>>> I believe this approach can solve two issues:
>>>>> - duplicate construction of the component tree - once in the markup and
>>>>> second time in Java code
>>>>> - auto components available only in the render phase
>>>>>
>>>>> Here is how I see it:
>>>>>
>>>>> Any MarkupContainer that wants to use markup-driven-tree must declare
>>>>> the
>>>>> components as member fields:
>>>>>
>>>>> private SomeComponent aComponent;
>>>>>
>>>>> These fields will be instantiated like any other component in Wicket:
>>>>>
>>>>> aComponent = new SomeComponent(id, ...);
>>>>>
>>>>> The new thing is that they *won't* be added to a parent component
>>>>> explicitly/manually.
>>>>>
>>>>> On Page#onInitialize() the first thing to do it to walk over the
>>>>>
>>>> component
>>>>
>>>>> tree from the page's markup (just like the walk in the rendering related
>>>>> code) and resolve the missing bits.
>>>>> I.e. while walking thru the markup tree we will check the Java component
>>>>> tree (container.get(tagId)). If there is a miss then we search for a
>>>>>
>>>> member
>>>>
>>>>> field that is a component with the same id in the current
>>>>>
>>>> MarkupContainer,
>>>>
>>>>> its (Java) super classes and finally in its (Wicket) parent classes.
>>>>>
>>>>> This will solve issue #1 (identical trees in Java and markup)
>>>>> (P.S. Fridolin's code uses @AutoComponent annotation that facilitates
>>>>> searching by component id, but will duplicate the declaration of the id
>>>>> -
>>>>> once in the annotation and second time in 'new MyComponent(ID). This is
>>>>>
>>>> an
>>>>
>>>>> implementation detail.)
>>>>>
>>>>>
>>>>> The second part is not less hard - during the walk over the markup tree
>>>>> when an autocomponent (e.g. enclosure) is seen Wicket will use the
>>>>> registered IComponentResolvers to create the Java component and insert
>>>>> it
>>>>> in the Java tree.
>>>>> The tricky part here is that any manually added components (like in
>>>>>
>>>> Wicket
>>>>
>>>>> 6.x) to the parent of the autocomponent should be moved into the
>>>>> autocomponent.
>>>>> For example:
>>>>>
>>>>> <div wicket:id="a">
>>>>>      <wicket:enclosure child="b">
>>>>>         <span wicket:id="b"></span>
>>>>>         <span wicket:id="c"></span>
>>>>>      </wicket:enclosure>
>>>>> </div>
>>>>>
>>>>> If 'b' and 'c' are added manually to 'a' in the application's Java code:
>>>>> (a (b,c))
>>>>>
>>>>> then after the "resolving phase" the tree will be:
>>>>>
>>>>> a (enclosure(b, c))
>>>>>
>>>>> so b.getParent() in onInitialize() and later will return the Enclosure,
>>>>>
>>>> not
>>>>
>>>>> 'a'.
>>>>>
>>>>>
>>>>> I don't know very well the MarkupStream APIs but I think all this should
>>>>>
>>>> be
>>>>
>>>>> possible.
>>>>>
>>>>> WDYT about this approach ?
>>>>>
>>>>>
>>>>> Martin Grigorov
>>>>> Wicket Training and Consulting
>>>>>


Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
On Fri, Jan 24, 2014 at 12:04 AM, Sven Meier <sv...@meiers.net> wrote:

> Hi,
>
> I don't think we're heading the right direction with this and I wouldn't
> advertise it as anything yet.
>

I'd like to advertise it anyhow now just to have more people feeding me
with stoppers, as you and Igor do. Thanks! :-)


>
> There are more questions to come but here is one upfront:
>
>
> >And it is configurable, by default disabled.
>
> As Igor has written, this does not work with component libraries which
> depend on the new feature.
> Couldn't this feature be enabled/disabled on a per-component basis? Why
> not make it a behavior that you can attach to components if you want to use
> automatic resolving/rearranging of its children?
>

- per-component basis - yes, as I explained earlier this is possible with
the current impl
- behaviors don't have hooks for onInitialize()
After Igor's feedback I think onAfterInitialize() is what is needed, so
apps can use onInitialize() as a complement to the constructor
Additionally I think using Behavior will add a bit more bytes to each
component than the current solution


>
> Regards
> Sven
>
>
>
> On 01/23/2014 05:20 PM, Martin Grigorov wrote:
>
>> Once the markup driven construction is done (just before onInitialize())
>> the application will have to use the old good add()/addOrReplace().
>>
>> The components are already in the MarkupContainer#children data structure.
>> So each field will add extra 8 bytes on 64bit machine (or 4 bytes with
>> CompressedOops enabled).
>> Serialization is the same - the object is written once, with several
>> pointers.
>>
>> I am also not fully sure in the approach but I am experimenting and so far
>> it works well.
>> And it is configurable, by default disabled.
>> We can advertise it as experimental ?!
>>
>> I will add more use cases/tests soon.
>> And caching for the reflection stuff.
>>
>>
>> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <ig...@gmail.com>
>> wrote:
>>
>>  what about components added in onInitialize() or on onConfigure()?
>>>
>>> this will also lead to a higher memory/serialization space usage since
>>> by default you need a field to store the component ref.
>>>
>>> not sure its worth doing it this way...
>>>
>>> -igor
>>>
>>>
>>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <mg...@apache.org>
>>> wrote:
>>>
>>>> Hi,
>>>>
>>>> Recently Fridolin Jackstadt shared his approach to "autowire" components
>>>>
>>> -
>>>
>>>> https://github.com/wicket-acc/wicket-autowire.
>>>>
>>>> I believe this approach can solve two issues:
>>>> - duplicate construction of the component tree - once in the markup and
>>>> second time in Java code
>>>> - auto components available only in the render phase
>>>>
>>>> Here is how I see it:
>>>>
>>>> Any MarkupContainer that wants to use markup-driven-tree must declare
>>>> the
>>>> components as member fields:
>>>>
>>>> private SomeComponent aComponent;
>>>>
>>>> These fields will be instantiated like any other component in Wicket:
>>>>
>>>> aComponent = new SomeComponent(id, ...);
>>>>
>>>> The new thing is that they *won't* be added to a parent component
>>>> explicitly/manually.
>>>>
>>>> On Page#onInitialize() the first thing to do it to walk over the
>>>>
>>> component
>>>
>>>> tree from the page's markup (just like the walk in the rendering related
>>>> code) and resolve the missing bits.
>>>> I.e. while walking thru the markup tree we will check the Java component
>>>> tree (container.get(tagId)). If there is a miss then we search for a
>>>>
>>> member
>>>
>>>> field that is a component with the same id in the current
>>>>
>>> MarkupContainer,
>>>
>>>> its (Java) super classes and finally in its (Wicket) parent classes.
>>>>
>>>> This will solve issue #1 (identical trees in Java and markup)
>>>> (P.S. Fridolin's code uses @AutoComponent annotation that facilitates
>>>> searching by component id, but will duplicate the declaration of the id
>>>> -
>>>> once in the annotation and second time in 'new MyComponent(ID). This is
>>>>
>>> an
>>>
>>>> implementation detail.)
>>>>
>>>>
>>>> The second part is not less hard - during the walk over the markup tree
>>>> when an autocomponent (e.g. enclosure) is seen Wicket will use the
>>>> registered IComponentResolvers to create the Java component and insert
>>>> it
>>>> in the Java tree.
>>>> The tricky part here is that any manually added components (like in
>>>>
>>> Wicket
>>>
>>>> 6.x) to the parent of the autocomponent should be moved into the
>>>> autocomponent.
>>>> For example:
>>>>
>>>> <div wicket:id="a">
>>>>     <wicket:enclosure child="b">
>>>>        <span wicket:id="b"></span>
>>>>        <span wicket:id="c"></span>
>>>>     </wicket:enclosure>
>>>> </div>
>>>>
>>>> If 'b' and 'c' are added manually to 'a' in the application's Java code:
>>>> (a (b,c))
>>>>
>>>> then after the "resolving phase" the tree will be:
>>>>
>>>> a (enclosure(b, c))
>>>>
>>>> so b.getParent() in onInitialize() and later will return the Enclosure,
>>>>
>>> not
>>>
>>>> 'a'.
>>>>
>>>>
>>>> I don't know very well the MarkupStream APIs but I think all this should
>>>>
>>> be
>>>
>>>> possible.
>>>>
>>>> WDYT about this approach ?
>>>>
>>>>
>>>> Martin Grigorov
>>>> Wicket Training and Consulting
>>>>
>>>
>

Re: Markup driven component tree

Posted by Sven Meier <sv...@meiers.net>.
Hi,

I don't think we're heading the right direction with this and I wouldn't 
advertise it as anything yet.

There are more questions to come but here is one upfront:

 >And it is configurable, by default disabled.

As Igor has written, this does not work with component libraries which 
depend on the new feature.
Couldn't this feature be enabled/disabled on a per-component basis? Why 
not make it a behavior that you can attach to components if you want to 
use automatic resolving/rearranging of its children?

Regards
Sven


On 01/23/2014 05:20 PM, Martin Grigorov wrote:
> Once the markup driven construction is done (just before onInitialize())
> the application will have to use the old good add()/addOrReplace().
>
> The components are already in the MarkupContainer#children data structure.
> So each field will add extra 8 bytes on 64bit machine (or 4 bytes with
> CompressedOops enabled).
> Serialization is the same - the object is written once, with several
> pointers.
>
> I am also not fully sure in the approach but I am experimenting and so far
> it works well.
> And it is configurable, by default disabled.
> We can advertise it as experimental ?!
>
> I will add more use cases/tests soon.
> And caching for the reflection stuff.
>
>
> On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <ig...@gmail.com>wrote:
>
>> what about components added in onInitialize() or on onConfigure()?
>>
>> this will also lead to a higher memory/serialization space usage since
>> by default you need a field to store the component ref.
>>
>> not sure its worth doing it this way...
>>
>> -igor
>>
>>
>> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <mg...@apache.org>
>> wrote:
>>> Hi,
>>>
>>> Recently Fridolin Jackstadt shared his approach to "autowire" components
>> -
>>> https://github.com/wicket-acc/wicket-autowire.
>>>
>>> I believe this approach can solve two issues:
>>> - duplicate construction of the component tree - once in the markup and
>>> second time in Java code
>>> - auto components available only in the render phase
>>>
>>> Here is how I see it:
>>>
>>> Any MarkupContainer that wants to use markup-driven-tree must declare the
>>> components as member fields:
>>>
>>> private SomeComponent aComponent;
>>>
>>> These fields will be instantiated like any other component in Wicket:
>>>
>>> aComponent = new SomeComponent(id, ...);
>>>
>>> The new thing is that they *won't* be added to a parent component
>>> explicitly/manually.
>>>
>>> On Page#onInitialize() the first thing to do it to walk over the
>> component
>>> tree from the page's markup (just like the walk in the rendering related
>>> code) and resolve the missing bits.
>>> I.e. while walking thru the markup tree we will check the Java component
>>> tree (container.get(tagId)). If there is a miss then we search for a
>> member
>>> field that is a component with the same id in the current
>> MarkupContainer,
>>> its (Java) super classes and finally in its (Wicket) parent classes.
>>>
>>> This will solve issue #1 (identical trees in Java and markup)
>>> (P.S. Fridolin's code uses @AutoComponent annotation that facilitates
>>> searching by component id, but will duplicate the declaration of the id -
>>> once in the annotation and second time in 'new MyComponent(ID). This is
>> an
>>> implementation detail.)
>>>
>>>
>>> The second part is not less hard - during the walk over the markup tree
>>> when an autocomponent (e.g. enclosure) is seen Wicket will use the
>>> registered IComponentResolvers to create the Java component and insert it
>>> in the Java tree.
>>> The tricky part here is that any manually added components (like in
>> Wicket
>>> 6.x) to the parent of the autocomponent should be moved into the
>>> autocomponent.
>>> For example:
>>>
>>> <div wicket:id="a">
>>>     <wicket:enclosure child="b">
>>>        <span wicket:id="b"></span>
>>>        <span wicket:id="c"></span>
>>>     </wicket:enclosure>
>>> </div>
>>>
>>> If 'b' and 'c' are added manually to 'a' in the application's Java code:
>>> (a (b,c))
>>>
>>> then after the "resolving phase" the tree will be:
>>>
>>> a (enclosure(b, c))
>>>
>>> so b.getParent() in onInitialize() and later will return the Enclosure,
>> not
>>> 'a'.
>>>
>>>
>>> I don't know very well the MarkupStream APIs but I think all this should
>> be
>>> possible.
>>>
>>> WDYT about this approach ?
>>>
>>>
>>> Martin Grigorov
>>> Wicket Training and Consulting


Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
Once the markup driven construction is done (just before onInitialize())
the application will have to use the old good add()/addOrReplace().

The components are already in the MarkupContainer#children data structure.
So each field will add extra 8 bytes on 64bit machine (or 4 bytes with
CompressedOops enabled).
Serialization is the same - the object is written once, with several
pointers.

I am also not fully sure in the approach but I am experimenting and so far
it works well.
And it is configurable, by default disabled.
We can advertise it as experimental ?!

I will add more use cases/tests soon.
And caching for the reflection stuff.


On Thu, Jan 23, 2014 at 6:09 PM, Igor Vaynberg <ig...@gmail.com>wrote:

> what about components added in onInitialize() or on onConfigure()?
>
> this will also lead to a higher memory/serialization space usage since
> by default you need a field to store the component ref.
>
> not sure its worth doing it this way...
>
> -igor
>
>
> On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <mg...@apache.org>
> wrote:
> > Hi,
> >
> > Recently Fridolin Jackstadt shared his approach to "autowire" components
> -
> > https://github.com/wicket-acc/wicket-autowire.
> >
> > I believe this approach can solve two issues:
> > - duplicate construction of the component tree - once in the markup and
> > second time in Java code
> > - auto components available only in the render phase
> >
> > Here is how I see it:
> >
> > Any MarkupContainer that wants to use markup-driven-tree must declare the
> > components as member fields:
> >
> > private SomeComponent aComponent;
> >
> > These fields will be instantiated like any other component in Wicket:
> >
> > aComponent = new SomeComponent(id, ...);
> >
> > The new thing is that they *won't* be added to a parent component
> > explicitly/manually.
> >
> > On Page#onInitialize() the first thing to do it to walk over the
> component
> > tree from the page's markup (just like the walk in the rendering related
> > code) and resolve the missing bits.
> > I.e. while walking thru the markup tree we will check the Java component
> > tree (container.get(tagId)). If there is a miss then we search for a
> member
> > field that is a component with the same id in the current
> MarkupContainer,
> > its (Java) super classes and finally in its (Wicket) parent classes.
> >
> > This will solve issue #1 (identical trees in Java and markup)
> > (P.S. Fridolin's code uses @AutoComponent annotation that facilitates
> > searching by component id, but will duplicate the declaration of the id -
> > once in the annotation and second time in 'new MyComponent(ID). This is
> an
> > implementation detail.)
> >
> >
> > The second part is not less hard - during the walk over the markup tree
> > when an autocomponent (e.g. enclosure) is seen Wicket will use the
> > registered IComponentResolvers to create the Java component and insert it
> > in the Java tree.
> > The tricky part here is that any manually added components (like in
> Wicket
> > 6.x) to the parent of the autocomponent should be moved into the
> > autocomponent.
> > For example:
> >
> > <div wicket:id="a">
> >    <wicket:enclosure child="b">
> >       <span wicket:id="b"></span>
> >       <span wicket:id="c"></span>
> >    </wicket:enclosure>
> > </div>
> >
> > If 'b' and 'c' are added manually to 'a' in the application's Java code:
> > (a (b,c))
> >
> > then after the "resolving phase" the tree will be:
> >
> > a (enclosure(b, c))
> >
> > so b.getParent() in onInitialize() and later will return the Enclosure,
> not
> > 'a'.
> >
> >
> > I don't know very well the MarkupStream APIs but I think all this should
> be
> > possible.
> >
> > WDYT about this approach ?
> >
> >
> > Martin Grigorov
> > Wicket Training and Consulting
>

Re: Markup driven component tree

Posted by Igor Vaynberg <ig...@gmail.com>.
what about components added in onInitialize() or on onConfigure()?

this will also lead to a higher memory/serialization space usage since
by default you need a field to store the component ref.

not sure its worth doing it this way...

-igor


On Wed, Jan 22, 2014 at 12:12 PM, Martin Grigorov <mg...@apache.org> wrote:
> Hi,
>
> Recently Fridolin Jackstadt shared his approach to "autowire" components -
> https://github.com/wicket-acc/wicket-autowire.
>
> I believe this approach can solve two issues:
> - duplicate construction of the component tree - once in the markup and
> second time in Java code
> - auto components available only in the render phase
>
> Here is how I see it:
>
> Any MarkupContainer that wants to use markup-driven-tree must declare the
> components as member fields:
>
> private SomeComponent aComponent;
>
> These fields will be instantiated like any other component in Wicket:
>
> aComponent = new SomeComponent(id, ...);
>
> The new thing is that they *won't* be added to a parent component
> explicitly/manually.
>
> On Page#onInitialize() the first thing to do it to walk over the component
> tree from the page's markup (just like the walk in the rendering related
> code) and resolve the missing bits.
> I.e. while walking thru the markup tree we will check the Java component
> tree (container.get(tagId)). If there is a miss then we search for a member
> field that is a component with the same id in the current MarkupContainer,
> its (Java) super classes and finally in its (Wicket) parent classes.
>
> This will solve issue #1 (identical trees in Java and markup)
> (P.S. Fridolin's code uses @AutoComponent annotation that facilitates
> searching by component id, but will duplicate the declaration of the id -
> once in the annotation and second time in 'new MyComponent(ID). This is an
> implementation detail.)
>
>
> The second part is not less hard - during the walk over the markup tree
> when an autocomponent (e.g. enclosure) is seen Wicket will use the
> registered IComponentResolvers to create the Java component and insert it
> in the Java tree.
> The tricky part here is that any manually added components (like in Wicket
> 6.x) to the parent of the autocomponent should be moved into the
> autocomponent.
> For example:
>
> <div wicket:id="a">
>    <wicket:enclosure child="b">
>       <span wicket:id="b"></span>
>       <span wicket:id="c"></span>
>    </wicket:enclosure>
> </div>
>
> If 'b' and 'c' are added manually to 'a' in the application's Java code:
> (a (b,c))
>
> then after the "resolving phase" the tree will be:
>
> a (enclosure(b, c))
>
> so b.getParent() in onInitialize() and later will return the Enclosure, not
> 'a'.
>
>
> I don't know very well the MarkupStream APIs but I think all this should be
> possible.
>
> WDYT about this approach ?
>
>
> Martin Grigorov
> Wicket Training and Consulting

Re: Markup driven component tree

Posted by Martin Grigorov <mg...@apache.org>.
At
https://git-wip-us.apache.org/repos/asf/wicket/repo?p=wicket.git;a=commitdiff;h=6ba324dba2eab841cedc5426f4560946f8688b10you
may see a very simple demo of the idea.

A new test is added - a base page with three component which are *not *added
to the page and three specializations of that page without Java code but
different markup (different component tree).

Martin Grigorov
Wicket Training and Consulting


On Wed, Jan 22, 2014 at 10:12 PM, Martin Grigorov <mg...@apache.org>wrote:

> Hi,
>
> Recently Fridolin Jackstadt shared his approach to "autowire" components -
> https://github.com/wicket-acc/wicket-autowire.
>
> I believe this approach can solve two issues:
> - duplicate construction of the component tree - once in the markup and
> second time in Java code
> - auto components available only in the render phase
>
> Here is how I see it:
>
> Any MarkupContainer that wants to use markup-driven-tree must declare the
> components as member fields:
>
> private SomeComponent aComponent;
>
> These fields will be instantiated like any other component in Wicket:
>
> aComponent = new SomeComponent(id, ...);
>
> The new thing is that they *won't* be added to a parent component
> explicitly/manually.
>
> On Page#onInitialize() the first thing to do it to walk over the component
> tree from the page's markup (just like the walk in the rendering related
> code) and resolve the missing bits.
> I.e. while walking thru the markup tree we will check the Java component
> tree (container.get(tagId)). If there is a miss then we search for a member
> field that is a component with the same id in the current MarkupContainer,
> its (Java) super classes and finally in its (Wicket) parent classes.
>
> This will solve issue #1 (identical trees in Java and markup)
> (P.S. Fridolin's code uses @AutoComponent annotation that facilitates
> searching by component id, but will duplicate the declaration of the id -
> once in the annotation and second time in 'new MyComponent(ID). This is an
> implementation detail.)
>
>
> The second part is not less hard - during the walk over the markup tree
> when an autocomponent (e.g. enclosure) is seen Wicket will use the
> registered IComponentResolvers to create the Java component and insert it
> in the Java tree.
> The tricky part here is that any manually added components (like in Wicket
> 6.x) to the parent of the autocomponent should be moved into the
> autocomponent.
> For example:
>
> <div wicket:id="a">
>    <wicket:enclosure child="b">
>       <span wicket:id="b"></span>
>       <span wicket:id="c"></span>
>    </wicket:enclosure>
> </div>
>
> If 'b' and 'c' are added manually to 'a' in the application's Java code:
> (a (b,c))
>
> then after the "resolving phase" the tree will be:
>
> a (enclosure(b, c))
>
> so b.getParent() in onInitialize() and later will return the Enclosure,
> not 'a'.
>
>
> I don't know very well the MarkupStream APIs but I think all this should
> be possible.
>
> WDYT about this approach ?
>
>
> Martin Grigorov
> Wicket Training and Consulting
>