November 13, 2012

Best Practice Apache Wicket

There are some guidelines written about the best way how to use Apache Wicket, but I think I might have some more to contribute to all the things that has already been written.

1. And maybe the most important is always use Wicket Models.

First Wicket is a component based framework, which in itself implies you should always use Wicket Models.

Secondly wicket is also a framework that out of the box handles the back button dilemma, which is what should happen when the user press the back button in the web browser? Wicket handles this by versioning every page. Which means that if a user have in entered some data in a HTML form, then submitted and thereafter presses back button, Wicket will then out of the box present the values the way it was before pressing submit AND keeping you server Model in synch. You can get a good feeling of the above by playing around with the form example at http://www.wicket-library.com/wicket-examples/forminput/.

To achieve this Wicket uses the HTTP Session to store the previously pages states. To not now blow the RAM space on the server, you should almost always use the LoadableDetachableModel.

Be sure you have completely have understood the antipatterns at https://cwiki.apache.org/WICKET/best-practices-and-gotchas.html#BestPracticesandGotchas-Antipatterns.

The second and maybe finally most important Model is the CompoundPropertyModel. And remember that you can wrap Model. Example of that is:
class PersonList extends ListView<Person> {

    private static final long serialVersionUID = 1L;

    public PersonList(final String id, final IModel<List<Person>> model) {
        super(id, model);
    }

    @Override
    protected void populateItem(final ListItem<Person> item) {
        item.setModel(new CompoundPropertyModel<Person>(item.getModel()));
        item.add(new Label("id"));
        item.add(new Label("name"));
        // ...
    }
}

2. To keep wicket code more readable, avoid using anonymous inner classes.

Wicket as well as Swing code can blow up in your face when it comes to anonymous inner classes. Instead write separate classes in the same WebPage class, like the above example. Which result in in a much more cleaner code.
public class PersonPage extends WebPage {

    private static final long serialVersionUID = 1L;

    public PersonPage(final PageParameters parameters) {
        super(parameters);
        IModel<List<Person>> persons = ...;
        add(new PersonList("personList", persons));
    }
}

3. Try to only use the PageParameters constructor

Example of that you can see in the above PersonPage example. The reason for that is now you page can always be bookmarkable. Which the default constructor also can be, but it is more generic to directly use the PageParameters constructor, in case you later need to use a page parameters.

 

4. Do not try to reinvent the wheel when it comes to graphical components.

Wicket comes with a rich set of ready to use graphical components. Be sure to import them in your pom file.
<dependency>
    <groupid>org.apache.wicket</groupId>
    <artifactid>wicket-core</artifactId>
    <version>${wicket.version}</version>
</dependency>

<dependency>
    <groupid>org.apache.wicket</groupId>
    <artifactid>wicket-extensions</artifactId>
    <version>${wicket.version}</version>
</dependency>

<dependency>
    <groupid>org.apache.wicket</groupId>
    <artifactid>wicket-datetime</artifactId>
    <version>${wicket.version}</version>
</dependency>

If you need more have a look at http://wicket.visural.net/examples/, which have a nice WYSIWYG editor and a spinner.
Also since Wicket 6 is jQuery the backend library for Ajax. Look for example at the jQuery modal window at http://www.wicket-library.com/wicket-examples/ajax/modal-window.

 

5. Use Wicket XHTML namespace

See https://cwiki.apache.org/WICKET/wickets-xhtml-tags.html

 

6. Be sure you have configured Maven Jetty Plugin to restart whenever you have made code changes

<plugin>
    <groupid>org.mortbay.jetty</groupId>
    <artifactid>jetty-maven-plugin</artifactId>
    <version>${jetty.version}</version>
    <configuration>
        <scanintervalseconds>1</scanIntervalSeconds>
        <usetestclasspath>true</useTestClasspath>
        <connectors>
            <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
                <port>8080</port>
                <maxidletime>3600000</maxIdleTime>
            </connector>
        </connectors>
    </configuration>
</plugin>

7. And remember you can always debug your Wicket code with a JUnit.

Wicket has a great support for module testing support. But these test cases can also be used for debugging. When generating a Wicket project with the archetype you get a single JUnit test case with that you can start Jetty and then simply add breakpoints and you can debug your code.

References:

No comments: