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 <mgrigo...@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 <s...@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 <mgrigo...@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 <mgrigo...@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 <
> mgrigo...@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 <
> >>>>> mgrigo...@apache.org>wrote:
> >>>>>
> >>>>>
> >>>>>> On Fri, Jan 24, 2014 at 9:48 AM, Sven Meier <s...@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 <s...@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.vaynb...@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 <
> >>>>>>>>>>> mgrigo...@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
> >>>>>>>>>>>>
> >>>>>>>>>>>>
> >>>>>>>>>>>>
> >
>

Reply via email to