General Questions Why "Wicket"?

The name "wicket" was at first selected simply because it was unique, memorable and easy to say... and yet not used by a serious software project (the owner of the "dodgy IRC bot" called "wicket" which shows up in a Google search was kind enough to give his blessings to me via email to use the name). It is surprisingly hard to find any short word that is not already used as the name of some software project or other!

Although the name was selected for no particular reason, there are a couple of interesting coincidences. For one thing, web frameworks have been somewhat of a "sticky wicket". For another, "wicket" sounds a bit like "wiki" which is Hawaiian for "quick" (you could even think of the name as "wik" "it" ;-)). And finally, the original meaning of wicket was that of a small door. But, especially a small door within a larger door. I like this image quite a lot. It's modular ;-) and doors represent freedom (from the big J2EE door?). A picture of a small door within another door might make a nice cover for the User's Guide when it's done. Either that or a cute little squirrel staring back at the reader through a croquet wicket!

Design Philosophy Why are so many classes and methods in Wicket final?

Classes and methods in Wicket are generally declared as final until the need for extensibility is well understood. While this defensive approach may seem obsessive to some, the major benefit is that classes and methods which haven't been designed for extension cannot be extended until the problem(s) at hand are examined by the Wicket development team. This helps to ensure that the best approach is taken. Sometimes, straightforward extension is not the best approach. Sometimes, features of the API have been misapplied or misunderstood. It's best to catch this early.

While this does provoke more discussion and sometimes a bit of annoyance, the discussion generally improves Wicket and will help ensure greater backwards compatibility in the future. It's really a matter of how the development team manages API commitments. By making fewer commitments in the API in terms of extension points, we are more likely to be able to support those extension points that we do allow in the future. We are also more likely to catch anti-pattern use cases and provide features appropriate to the problems you are trying to solve.

Honestly, we aren't trying to annoy anyone and we do aim to respond quickly to any extension needs that arise which make sense. If you really don't agree with all this, remember that Wicket is open source. You can always check out the source code, remove the final keyword that offends you and rebuild the project.

What design decisions were made regarding state management?

There are probably only a small percentage (perhaps 20%-30%) of all web applications written that have to scale up to large clusters of machines with hundreds of concurrent users. Unfortunately, many web application frameworks are built around the assumption that everyone wants to build web applications of this size. The result being that people with the skills and resources available to build such applications are happy, while the other 80% of people are forced to jump through many hoops and do loads of manual state management that is not really necessary for the size of application they are building.

Wicket adopts an alternative approach. What we have tried to do is build a framework where out of the box (and for perhaps 50%+) of applications the developers do not need to worry about state management at all. No need to directly access the session, no need to enlist the help of second level caches or to manually reconstruct object state for each request and so on. Application developers can be more productive and the learning curve for Wicket is far lower.

One of the primary objectives was to make state management a Java thing that is abstracted away from implementation details like HttpSession. In Wicket, state is stored in components that are nested in Pages which are all contained in a map in the user's session. All of this is very well defined and occurs "behind the scenes".

Such a style of coding may be unfamiliar to people with experience using existing frameworks. Typically Wicket code involves good OO design, use of nested and anonymous classes and an overall awareness of components and their models as being the repositories of all state. It will take time to adapt to this and for people to set aside old functional models of programming where they accomplish everything with query parameters, session state or their equivalent.

That said, we also recognise the need to build large, highly scalable web applications using Wicket. Therefore, Wicket has a number of interfaces where we have adopted the strategy design pattern and where people needing to build large, scalable applications can take control and implement their own alternative approaches. As Wicket develops further we will probably provide our own implementations of the most common alternative approaches.

Can I control how Wicket managed its session state?

The default Wicket behaviour is to use the HttpSession object to hold a Wicket WebSession object and object hierarchies for each of the current active pages for any session (you can control how many in the settings). When new pages are created they are added to the s ession, when pages are no longer needed they are expired (removed) from the session. When an event arrives in a request for a particular page it is retrieved from the session and the event passed to the appropriate component listener. At the end of the request, any pages that have been accessed are marked as dirty and readded to the session to force cluster replication to occur. This approach provides transparent state management and enables near transparent support of the browser back button. However, we would agree that this approach does store a reasonable volume of objects in the session and causes some amount of cluster replication (but this may be fine for many applications, where the saving in development time far outweighs the cost of some extra processor or memory).

When such use of the session is prohibitive, Wicket offers a range of options for tuning the session usage:

  1. Detachable models can be used behind each component so that the model objects only hold an id value (or even nothing if you wish) and the actual business objects can be detached at the end of one request and reattached at the start of the next. You can then implement any second level approach that you wish in the attach/detach methods.
  2. Developers can manually override the page dirty state if they know that the event listener that was just invoked for a page did not cause any alterations to the page or model objects. This can be particularly useful to reduce unnecessary cluster replication.
  3. It is possible to override the PageState mechanism so that each page (or a base class for a group of pages) can control its own state replication. Thus instead of the entire page hierarchy of objects being added to the session, the custom PageState can hold just a minimum of state data and then reinstantiate the page again for the next request, or adopt some alternative approach - the choices are endless (and probably different for each application or group of pages within an application).

Longer term (Wicket 1.1) we are planning to add some additional approaches such as externalizing state to the client, stateless pages and allowing listeners that are not attached to pages for handling requests that do not require existing page state.

How does Wicket handle stale data and the back button?

Because Wicket has a first class component object model where the state for every page and nested component is available in the user's session, it can trace through all that state when model information changes looking for pages containing components with models that have changed in ways that invalidate earlier renderings of those components and pages.

This provides automatic handling for the back button, which has to do with stale markup, and can generally be divorced from the typical problems of stale data in a multi-user environment, which should be handled with the usual (optimistic) locking techniques in the persistence layer.

A good example of stale markup is this: If a table on a page is rendered when there are 20 rows in the table's model, a subsequent deletion of a row will invalidate the rendering of the table that is still cached in the user's browser. When the user accesses the 20th row in the cached page by using their back button, the link will not be backed correctly. What's more, a deletion of the first row means that all 19 rows are off by one in terms of the model they reference.

In Wicket, stale markup caused by deleting a row in a table is automatically handled by using the well-controlled server side state which exists in the user's session. If you look at the Cell class you will see this implementation (roughly) of the removeLink method (which returns a Link that will remove any given cell from its containing table).

Notice that once the remove link changes its table's model by removing the cell's model from the table list, it calls table.invalidateModel(). This method is implemented by Table, which inherits most of the functionality from Component. If you look at the implementation of invalidateModel in Component, you will find that it looks through every component on every page in the user's session. Any page containing a component using the same model is a stale markup rendering and is made stale with a call to setStale. When a user uses their back button to access the stale page at a later time, they will receive an appropriate warning.

Building your own Applications How can I set a session property?

The best and safest way to set a property for a session is to create a subclass of Session (for web applications, a subclass of WebSession) which has the properties you desire. Then override the getSessionFactory() method of Application and provide code which instantiates instances of your session subclass. For example:

Then you can provide access to session properties in a typesafe manner that requires only a single downcast in your whole project:

How can I get Wicket to automatically reload changed markup files?

By default, Wicket will not reload changed markup files. This default is a conscious decision because performance can be affected by Wicket's change detection code, which has to poll the modification dates of all your markup files at a regular interval.

If you call the ApplicationSettings method setResourcePollFrequency(Duration), you can specify how frequently Wicket should poll for file changes. A Duration value of null will turn the feature back off again. For example:

will cause Wicket to scan your source files for changes as often as every second.

Note that this does NOT affect where Wicket finds resources. If you want Wicket to find markup files directly in your source tree while you are developing, you can call setSourcePath(Path) like this:

This is a highly productive way to work if your resource poll frequency is fairly quick. After you change a markup source file, you can simply hit refresh in your brower and immediately see the effect. With your source path set like this, it is not necessary to restart the application server or redeploy any files.

Finally, it is interesting to note that since ApplicationSettings methods return their this pointer for invocation chaining, you can put this all together into one statement:

How can I hide markup and/or components? Any component - whether a simple label, form component or a whole panel - can be hidden with a call to setVisible(false). A WebMarkupContainer is a container component that can be attached to any tag. Since WebMarkupContainer is a component, you can call setVisible(false) on it and it will hide whatever it contains, whether it's just markup or a whole tree of nested components. For example:
this row will be hidden
this row will not be hidden
]]>