This page will contain the accumulated thoughts on what the wicket best practices are. It will also list situations that cause erroneus behaviours and are hard to track down.
Html Template Declaration
Do's and dont
Do use models
Don't do this
But this -
Or even this:
Why - because A) we don't want to risk serialize an object, models are fine though - lightweight and ok. And we want to let the component take care of the detach when the request is done B) With an direct-entity we would set an nondynamic value to our label. With a model, the label will update the value from the entity it's using.
Don't use an Ajax library without intimate knowledge of the library
May collide with wicket code, make sure you know your JS-library well
Do make sure you understand the repeaters for high performance sites
Wicket by default provides the following repeater: Loop, ListView, RepeatingView, RefreshingView, DataTable. This list is not even exhaustive; there are some more variations. Every repeater constructs a transient component for each iteration: the loop item. Every loop item has a Wicket model to look up the item's data.
Here are some points to consider to choose the most optimal repeater:
- Moment of data retrieval. Is it during construction only, or for each render again?
- During a re-render, is all data retrieved at once or one by one?
- Moment the loop-item's model is created. First time only, or again for each render, or does it retain existing models and only add/remove models as the underlying data changes (ItemReusePolicy)?
- Can you control the model creation?
- Is pagination/sorting needed?
Don't overuse inheritance - use composition
Signs you're in trouble are:
- common layout turned out to be slightly different on every page,
- components are created by abstract methods (constructors should not call these),
- there are getters to your components (breaks data hiding),
- the constructor of the sub-class replaces a component that was created by the super-class (wasteful and unmaintainable) or
- you add components while the wicket:id is not in the markup file of the current class (maintenance nightmare).
The remedy is to split of parts of the screen to separate components (e.g. Panels) and manage the complexity there.
Don't try to do authorization from a servlet filter
It just won't work. Wicket is full of generated URLs (yes, even if you mount every page) so authorization based on the URL is a fruitless exercise. You are better off by writing an IAuthorizationStrategy and configuring this in your Wicket application. Study the code of wicket-auth-roles to see how this can work. In addition you'll get component based authorization, not just page based! (By the way, you'll have no problems with filter based authentication.)
Do take your time to override key Wicket features
Wicket can be tweaked in all kinds of expected and unexpected ways. For example you can substitute your own resource messages provider, filter and change the markup as it is read from disk or completely override the request cycle handling. However, some of these extension points are not for the faint hearted and not likely to be right immediately
onInitialize for adding components.
If you need to , and 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.
Wicket Filter Mapping
Wicket 1.4.x and upwards
On these versions, you should prefer to use WicketFilter instead of WicketServlet. If you want, it's possible to map
/* instead of
/app/*. But remember to configure the
ignorePaths parameter to ignore static resources and leave them to be handled by the container.
If you want to leave static resources to be handled by the container, configure the
ignorePaths init parameter as follows:
Otherwise, there's a risk the wicketservlet will handle the job to serve static resources, instead of the container.
For example,let's say you have
/myapp/images/foo.gif and you map your wicket servlet to
/* and dpn't have set ignorePaths.
Here is the correct way to do this
The entity is fetched each page view, and NOT serialized with the page. The only thing that gets serialized is the fetching model.
Here is the correct way to do this:
The PropertyModel holds a reference to the Model which fetches the User on each page view. That way the User object is always fresh and is not serialized with the page.
Here is the correct way to do this, though not very elegant.
antipattern 1-3 from blog letsgetdugg, thanks
Anti-pattern #4. - Anonymous Inner classes
Don't do this:
The 'subject' instance of the MyVeryLargeObjectDao class will be serialized into the session with each page version. This can get out of hand, because with some business object models, the attached object can become very large. For this we introduced DetachableModels, which will retrieve the data from the database when needed, and will clean up when the data is not needed (at the end of the request for instance).
The other thing to be careful about are anonymous or nested subclasses of IModel. Usually you shouldn't share an instance of a model between two page instances. But if you create an anonymous or nested instance of IModel, then you automatically get a 'this' reference to the class that surrounds it. This will usually be the page, but can also be the form or a listview. Anyway, because the reference is /final/, you will copy that reference to the old page, with the model to the new page, thus duplicating the component tree (it gets versioned etc.). This will eventually lead to OutOfMemoryError.
Search in the mailinglist for outofmemoryerror for other descriptions of this behaviour. I doubt that I have done the subject justice.
''Martijn Dashorst - Extracted from wicket-user mailing list
If you get a
NotSerializableException on a deeply nested class like
MyClass$2$1$1, it can be difficult to figure out which part of your code is causing the problem.
javap, but be sure to escape the
Empty URL Parameter in CSS Style ( background-image: url(""); )
I ran into this problem where clicking on links in DataTable's generated an internal error in wicket and an error log indicating that the requested component was not found. Strangely, the case was only with Firefox and I had no problem with IE.
After debugging and digging everywhere, I found the cause was an empty image style attribute in my page causing firefox to re-generate a request to the page after the page has been shown, which would in turn re-render the component tree and invalidate the previous components:
This kind of problem is tricky to detect and even if it isn't causing any errors it would generate an extra load on servers.
BODY:onLoad in Panel not added without wicket:head
Taken from the mailing list. Question by Joshua Lim, answer by Juergen Donnerstag
Adding wicket:head to a Page
The <wicket:head> pair can be used in Panels, Borders and Fragments, and is used for doing a 'header contribution', meaning that the contents will be written to the <head> section of the page the component is placed in. If you are authoring a normal page, you don't need <wicket:head> tags but instead put it in the page's head section directly. The exception to this is when you use markup inheritance, and one of the pages to extend wants to contribute to the header of some extending page, and the header is not part of the <wicket:extend> region. In that case, you can use <wicket:head>.
Starting download after form submission (Wicket 1.1)
If you want to respond with a download to a form submission, you have to set the response page to null after writing your data into the response.
See wicket.examples.displaytag.export.Export for a more complete example.
Starting download after form submission (Wicket 1.2)
The same as for 2.0, except that target.setFileName is from 1.2.3. You can override configure, cast to WebResponse, and call setAttachmentHeader on the response like this:
or do it like this:
Starting download after form submission (Wicket 2.0)
This can be achieved using code like this (2.0):
PackageResources and relative paths
Assuming you have the following directory structure:
with the following Application.mountBookmarkablePage() rules:
Keep in mind that the path argument in the PackageResource methods ignores any Application mount() rules you might have applied. So it is legal to write:
but it is not legal to write:
PBEWithMD5AndDES not found
[For the moment, I'll leave this, but I'm not convinced this actually belongs here at all - Gwyn 13:56, 23 Aug 2006 (BST)]
Not entirely clear what causes this.
A possible fix is to add another security provider like this:
- download http://www.bouncycastle.org/download/bcprov-jdk15-133.jar
- put it in jre\lib\ext
- in java.security (jre\lib\security), add this security provider:
[Comments on the mailing list suggest this has been seen twice only, and may be due to misconfigured/corrupted JDK - Suggest reinstalling the JDK before adding BouncyCastle... Gwyn 13:56, 23 Aug 2006 (BST)]
I've only seen this under the SysDeo Tomcat plug-in for Eclipse, when the boot classpath wasn't configured properly to include jce.jar, etc. – Al Maw
I ran into a similar problem with Red Hat Enterprise Linux because the default JDK is from IBM, and I had to replace wicket's SunJceCrypt and CachingSunJceCryptFactory with my own IBM versions. – Jim Hunziker
Adding id attribute to a tag
This is due to a hard to fix issue. As long as that issue is open, people should avoid setting id attributes on tags that are coupled to components that use rely on the markup id (setOutputMarkupId true). See http://issues.apache.org/jira/browse/WICKET-694 – Eelco
Avoid using empty elements (i.e. <textarea />)
Wicket will not automatically expand an empty element (i.e., an element that is expressed as a single tag ending in "/>") during the rendering phase. You should always include both an open tag and a close tag in your markup when you want Wicket to include content in the tag body.
Links with stuff not yet integrated:
http://www.devproof.org/wicket_best_practice - Devproof best practices
http://blog.worldturner.com/worldturner/entry/wicket_best_practices_components_vs blog worldtuner
http://www.small-improvements.com/10-things-about-apache-wicket-i-love/wicket:pageMapName/wicket-0 - 10 things to know..
http://stronglytypedblog.blogspot.se/2009/04/wicket-patterns-and-pitfalls-5.html Wicket pitfalls 5 articles
http://wicketinaction.com/ in action - lots of good stuff if searching here