General Questions

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!

We feel that there are several issues with discussion forums and a lot
of advantages when using mailinglists as a main discussion and support platform.
We like having just one method of communicating with our users and co-developers.
When we introduce message boards, mailinglists, and whatnot kind of discussion
platforms, we have to monitor all those platforms. As all core-developers work on
Wicket in their free time or some spare minutes during working hours answering
e-mail on the lists, we are limited in our time to monitor all those different
platforms and answer all questions or discuss design issues. In this case: less
is more. Less communication platforms means more attention from the developers.

Mailinglists allow us to monitor user and development questions directly. Usually
you get a response within minutes from either a core developer or another user.
The current mailinglists have been very kind to us and our users.

Mail is often not blocked on corporate networks. Several corporations block
non-approved websites. Discussion forums are necessarily website based. We
don't have to go to a website and refresh the discussion groups constantly in
order to see what has happened. Discussion websites are usually very bad at
searching and browsing for information.

E-mail clients have better editors, and support (when using a good e-mail program)
threaded views of mail messages. For instance Mozilla Thunderbird supports this.
If your mail client doesn't support threaded views, you can always use
gmane.comp.java.wicket.user or
gmane.comp.java.wicket.develop in
a News client.

And finally most
Wicket users prefer mailinglists over discussion forums. (Check out the votes in
the linked thread).

We strive to make Wicket available for the largest possible number of developers. This
means that we have to take into account those developers that don't have the luxury of
running their application servers on Java 5. Many shops don't run on Java 5 yet. We would
be doing ourselves and our users a great disservice when we would target Java 5 as our
base platform.

As several members of our community have pointed out, there is a code converter for
running Java 5 code on a Java 1.4 runtime, RetroWeaver.
Even though it is a remarkable product, and probably works flawlessly, we, the
Wicket core team, can't support using such a tool on a framework. Debugging web applications
is already a very complex thing to do, and when we introduce such an unknown component (or
to be more precise: 2 components), bug finding becomes even harder. Furthermore, some clients
of our users won't or can't accept such retrofitted code.

Also note that RetroWeaver only takes your source code into consideration. The standard libraries,
which are an integral part of a Java Runtime Environment, are not backported. For instance, Wicket
uses the
concurrent
package of Doug Lea. This package has been adopted
by the Java 5 runtime library. However the backport of this JDK 1.5 extension is not a 1-on-1
drop in library that makes our code ready for JDK 1.5. Java explicitly forbids that other than
the Java Runtime Library classes contribute to the java.xxx namespace. So supplying
the backport with Wicket will not solve our problem.

Please keep in mind that we do see the benefits of using Java 5. We like annotations, generics,
autoboxing, removing the need for concurrent.jar, etc. But we have to look at the world around us,
and that world is unfortunately not using Java 5.

Basically a large part of the answer is: when the majority of our customers can run their web
applications on Java 5. As IBM WebSphere is one of the leading application servers, having Java
5 support for WebSphere application server is one condition.

Furthermore, upgrading to Java 5 will break a lot of stuff, so this will be scheduled for a major
release. At the moment this is scheduled for Wicket 2.

We would like to give other functional requirements a higher priority, like AJAX and Portlet support,
as those will help all users of Wicket. So first Wicket 1.1 and 1.2 will see the light of day,
after that we will see what needs to be done.

Design Philosophy

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.

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.

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:

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.

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.

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.

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

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:

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:

<![CDATA[settings.setResourcePollFrequency(Duration.ONE_SECOND)]]>

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:

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: