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