Using onInitialize() to establish components instead of the constructor
makes sense for many reasons.
One of the most important reasons is what we discovered in the early
days of Wicket: the code executed in a constructor is executing before
the object is fully constructed i.e. before virtual method tables are
ready for use.
This means that if your page or panel is part of a class hierarchy and
you rely on overridden methods they will not always perform correctly.
However, because onInitialize() is called by the Wicket framework after
construction, all overridden methods will perform correctly.
We were using an overridden getVariation() method in our Page class
hierarchy and things weren't working when calling that method in the
constructor (which is why, many years ago, we asked the awesome Wicket
devs to introduce a separate overridable onInitialize() method called
after construction - which they did! - and everything was awesome for us
after that =] ).
Something else that may help your need to implement flexible assembling
of components: dynamic component creation.
This basically means that your component hierarchy can be dynamically
assembled, as dictated by the markup. i.e. add a new panel to a page's
markup using a specific component Id and during page rendering the
appropriate Java component will be automatically instantiated and added
to the parent.
The implementation of this feature was non trivial but has been so
useful it has paid off big time.
Basic concept:
Implement a class called ComponentLibraryResolver which has a static
method addDynamicComponents(MarkupContainer container,
DomainSpecifcEntity domainSpecificEntity)
Have 'BasePage' that all pages in your app derive from.
In BasePage.onInitialize() calls
ComponentLibraryResolver.addDynamicComponents(this, myDomainSpecificEntity);
addDynamicComponents analyses the preparsed markup, looking for tagIds
that are marked to be auto created and any that it finds get created and
added to the container.
That's a bit oversimplified but you get the idea.
I think there is an interface in Wicket that allows you 'hook into' the
component creation part of the page rendering lifecycle but we ended up
not being able to use that for our use case ... from memory it might
have been due to our need to pass in our DomainSpecificEntity.
Regards,
Chris
On 4/05/2025 2:09 am, andrew goh wrote:
While working on an Apache Wicket app, I have some questions.
The example in the user guide(s) tend to put all the creation of the
page's component in the constructor()
https://nightlies.apache.org/wicket/guide/9.x/single.html#_the_homepage_class
However, I'm seeing that that approach has some downsides. For more
complex components e.g. forms or complex panels with many embedded
components (e.g. reusable tables forms, page layouts (e.g. menus)
etc). Sometimes a lot of parameters are passed to the constructor to
fill up the page / component.
There are often cases that some components has various options or
optional components. Currently, I'm handling that by declaring
different constructors so that the basic ones may have less
parameters, and where the options or optional components are needed,
they are passed into the page via constructors with more parameters.
Another downside is a javabean styled component where one can have a
no args constructor. And that the various parameters are updated using
getters and setters methods, e.g. with commons beanutils
(https://commons.apache.org/proper/commons-beanutils/).
I'm thinking about implementing component construction i.e.
initializing the various page components using onInitialize()
https://nightlies.apache.org/wicket/guide/9.x/single.html#_hook_methods_for_component_lifecycle
That means say if the web page codes looks like
public class HomePage extends WebPage {
public HomePage() {
add(new Label("helloMessage", "Hello WicketWorld!"));
}
}
it becomes
@Override
protected void onInitialize() {
super.onInitialize();
add(new Label("helloMessage", "Hello WicketWorld!"));
}
In fact, rather than pages, it is more likely that I use that with
components and override onInitialize().
In that sense, components can be constructed 'javabeans' style say
using a no args constructor and its properties set using getter and
setter methods.
Is this feasible, has anyone done this in an actual app?