

Do not pass entire components or pages to constructors of other components.

*Listing 12:*

{code}
// Bad solution
public class SettingsPage extends Page {
    public SettingsPage (IModel<Settings> settingsModel, final Webpage backToPage) {
        Form<?> form = new Form("form");
        // add components
        form.add(new SubmitButton("changeSettings") {
            public void onSubmit() {
               // do something
               setResponsePage(backToPage);
            }
        });
        add(form);
    }
}
{code}

The @SettingsPage@ expects the page which should be displayed after a successful submit to be passed to its constructor. This solution works, but is very bad practice. You need to know during the instanciation of @SettingsPage@ where you want to redirect the user. This requires a predetermined order of instanciation. It is better to order the instanciation based on business logic (e.g. the order in the HTML template). Furthermore, you need an unnecessary instance of the next success page which might never be displayed. The solution is once again the Hollywood principle. For this you create an abstract method or a hook:

*Listing 13:*

{code}
// Good solution
public class SettingsPage extends Page {
    public SettingsPage (IModel<Settings> settingsModel) {
        Form<?> form = new Form("form");
        // add components
        form.add(new SubmitButton("changeSettings") {
            public void onSubmit() {
               // do something
               onSettingsChanged();
            }
         });
         add(form);
    }

    // hook
    protected void onSettingsChanged() {
    }

// The usage of the new component
Link<Void> settings = new Link<Void>("settings") {
    public void onClick() {
        setResponsePage(new SettingsPage(settingsModel) {
            @Override
            protected void onSettingsChanged() {
               // reference to the current page
               setResponsePage(this);
            }
        });
    }
}
add(settings);
{code}

This solution has more code, but it is more flexible and reuseable. We can see there is an event @onSettingsChanged()@ and this event is called after a successful change. Furthermore, there is the possibility to execute additional code besides setting the next page. For example, you can display messages or persist information.