Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wicket: Where to add components? Constructor? Or onBeforeRender?

Tags:

java

wicket

I'm a Wicket newb. This may just be my ignorance of the Wicket lifecycle so please enlighten me! My understanding is that Wicket WebPage objects are instantiated once and then serialized. This has led to a point of confusion for me, see below.

Currently I have a template class which I intend to subclass. I followed the example in the Wicket docs demonstrating how to override the template's behavior in the subclass:

protected void onBeforeRender() {
        add(new Label("title", getTitle()));

        super.onBeforeRender();
}

protected String getTitle() {
        return "template";
}

Subclass:

protected String getTitle() {
        return "Home";
}

This works very well. What's not clear to me are the "best practices" for this. It seems like onBeforeRender() is called on every request for the page, no? This seems like there would be substantially more processing done on a page if everything is in onBeforeRender(). I could easily follow the example of the other Wicket examples and add some components in the constructor that I do not want to override, but then I've divided by component logic into two places, something I'm hesitant to do.

If I add a component that I intend to be in all subclasses, should I add it to the constructor or onBeforeRender()?

like image 420
gmallett Avatar asked Feb 06 '11 15:02

gmallett


2 Answers

For components that are not a Page, you can override the new onInitialize callback to add components, which is only called once after construction, when the component has been added to the page (so that component.getPage() doesn't return null).

Another option is to use addOrReplace() instead of add.

As for calling overridden methods in a constructor, try to do that in a Model or some other delayed callback. In your example the solution is much simpler:

public abstract class BasePage extends WebPage {
    public BasePage() {
        add(new Label("title", new PropertyModel<String>(this, "title")));
    }
    public abstract String getTitle();
}

Using a PropertyModel to retrieve the contents of the label is much better than pushing the value into the label.

like image 176
Martijn Dashorst Avatar answered Oct 21 '22 01:10

Martijn Dashorst


You should add components in the constructor as a rule to which there are very few exceptions. Roughly, there is a phase for setting up the hierarchy (construction), and a separate phase for rendering it. It is not recommended (and often prohibited) to mix the two.

like image 39
Eelco Avatar answered Oct 21 '22 02:10

Eelco