All posts by roger

Wicket components have a convenient getString method to load a (translatable string from a properties file associated with the component (or any component in its hierarchy). It also allows you to provide parameters to those strings in the form “${count} new messages” where count is looked up as a property of the model you pass to getString.

Sometimes, however, I’d prefer to just have simple numbered parameters and provide them as varargs to getString(). So, in my properties file, I’d have “${0} new messages” and I’d call “getString(id, 15)” to get “15 new messages”. To do this, you need to add a method something like this:

A common issue which Wicket developers face is the need for an AJAX update of the HTML output of a repeater (such as a ListView) which is part of a HTML table (where the repeating element is represented by a single <tr wicket:id=”mylist”> line in the table). The problem is that you can’t just use “target.addComponent(mylist)” – you need some kind of container around the repeater. Using a nested table or div as a container may interfere with your table layout.

The solution is to use a <tbody wicket:id=”mylistcontainer”> tag around the <tr> which you can add to your page with a WebMarkupContainer and then pass to target.addComponent. It provides you with a container around one or more table rows which you can address from Wicket without messing up your table layout.

Here’s something which took me several days to figure out. If you have form fields within a TabbedPanel (or AjaxTabbedPanel), how do you ensure that they get validated and submitted correctly when the user switches tabs . The TabbedPanel unloads panels as the user switches tabs so only the currently selected tab gets submitted. One suggestion (from Julian Sinai) was to use AjaxFormValidatingBehavior as follows:

AjaxFormValidatingBehavior.addToAllFormComponents(form, “onblur”);

This ensures that form fields get submitted every time they lose the focus (which also happens when the user switches tabs). This however still leaves us with the problem that the tab switch has already occurred before you have a chance to react to validation errors.

The solution I eventually found was to prevent the user switching tabs until any form fields within the selected tab validate correctly.

I did this by overloading the newLink method of the TabbedPanel and returning an AjaxSubmitLink instead of the standard AjaxFallbackLink (wouldn’t it make sense to make AjaxSubmitLink the default if the Panel contains form fields?). Since the AjaxSubmitLink needs a form, I needed to additionally extend the AbstractTab used by the TabbedPanel to query its panel for a form.

I needed to validate a list of email addresses entered into a Wicket text area (a cc: list of email addresses). To do this, I created a simple form validator which breaks up the list from the text area into individual email addresses and then uses the EmailAddressValidator to validate them individually. It illustrates a few Wicket techniques: (a) how to validate a field containing several values which need to be validated individually and (b) how to use a Validator against a string instead of a form component. Anyway, here’s the code in case its of use to anyone.

We just started using JRebel on a wicket project with hibernate and Spring. JRebel (formerly known as JavaRebel) provides true hot-swap development under Eclipse – i.e. you never have to republish and wait for hibernate and Spring to reload everything – whenever you save a class JRebel notices and simply reloads the class into the JVM. This greatly increases productivity on larger projects and, perhaps more importantly, removes a major annoyance factor relative to other languages which handle this better.

Installation was a bit confusing because JRebel does not watch for changed classes in the directory where Eclipse puts them by default (at least that was the case for our installation of Eclipse on Mac OS X). To workaround this, you need to add a rebel.xml file to the WEB-INF/classes directory of your project as follows:

Labels for checkboxes weren’t working as I expected in wicket panels (i.e. when I clicked the label, the checkbox didn’t react). Looking at the output html I saw that the id of the checkbox had been changed by wicket, so the “label for” was no longer associated with the checkbox. The solution was to use the label without the for (and nest the checkbox within the label tag).

We were wondering how to use Hibernate annotations to automatically create constraints (HTML “maxlength”) and validators (required fields, string length validation). After searching around, I found a wicket behavior for this in wicket-stuff from Ryan Sonnek. It was in wicket-stuff 1.3 and apparently had been removed from 1.4. Anyway, I patched it up a bit to make it work in wicket 1.4 and here it is (I also took the liberty of renaming it to AnnotatedConstraintBehavior in case we wanted to use it for annotations other than hibernate):

To use it, you’ll need to have @Length(min=x,max=y) and/or @NotNull hibernate annotations on your objects. The behavior will find these in component models and react accordingly, adding the maxlength attributes to the markup, string validator and setting required.

I implemented a simple extension of the wicket PasswordTextField which provides you with an indication of the strength of the entered password (using regular expressions and returning “empty”, “weak”, “medium” or “strong”). Strong means at least 7 characters with mixed alphanumeric and non-alphanumeric characters. Medium means at least 6 characters with mixed alpha and non-alpha characters.

Originally I intended to make it a panel with a visual indicator (the usual spectrum from red through yellow to green), but then I figured that allowing the caller to make the styling decisions is better (if you want to display a spectrum, then add images to your styles and set the style on the component using an AttributeModifier – come to think of it, maybe I’ll do another post on how to do that…).

// put a label on the form which will display the strength of the entered password
final Label passwordStrengthLabel = new Label("passwordStrength");
passwordStrengthLabel.setOutputMarkupId(true);
form.add(passwordStrengthLabel);
PasswordTextFieldWithStrength passwordField = new PasswordTextFieldWithStrength("password") {
private static final long serialVersionUID = 1L;
And here's how it looks in an application
@Override
public void onUpdate(String strength, AjaxRequestTarget target) {
// strength will be one of "empty", "weak", "medium", "strong"
// you can put it into a label, use it as a key to load a localized string, use it to construct a style etc
passwordStrength = getLocalizer().getString("passwordStrength_" + strength, this);
target.addComponent(passwordStrengthLabel);
}
};
form.add(passwordField);

Anyone who has a Mac is familiar with Time Machine, the almost magical, continuous backup capability of OSX. What many people may not know is that Time Machine is based on concepts which have been freely available for quite some time and which can easily be applied to corporate-wide backups. Because corporate backup is considered expensive to implement, many companies have outdated legacy backup systems based on tapes, tape-robots and offsite transport and storage of tapes. These systems are hopelessly outdated and can no longer keep up with the every increasing storage capacity of the disks they should be backing up and the decreasing backup time window in which backups should be completed.

We have approximately 3TB of data (consisting of about 40 databases, 200 virtual machines and hundreds of thousands of files) on our servers and workstations which need to be backed up. About a year ago we installed a comapny-wide backup to disk with offsite replication and versioning which has been providing us with continuous backup ever since. It continuously replicates a 4TB local RAID-6 disk-array offsite to a versioning 5TB RAID-6 disk array over a dedicated 4Mbps line, 24 hours a day, using rsync for the replication and snapshots based on Linux filesystem hard-links for versioning. Its implemented entirely on standard Linux components (zero license costs) and has been running without a glitch for over a year. Thanks to this system, we not only have an offsite backup of all business-critical data, but we can step back to any version of a database or virtual machine from yesterday, two days ago, four days ago, a week old, a month old etc. I can’t imagine why any company would still want to install a propietary backup system when such perfect technology is freely available.

This blog is running on a Turnkey WordPress appliance (www.turnkeylinux.org). Virtual appliances are of course fantastic if they work – a fully configured, just-works server which you can download and provision in seconds (this blog took about 5 minutes to download, install on a VMWare Server virtual machine and get running). Until now, most appliances we tried had enough gotchas to make us return to manual installation on a generic distribution, but the Turnkey appliances seem to be perfect. Based on Ubuntu or Debian and with just enough stuff pre-installed to make them useful, while still being compact enough to compete with a manual installation. Thanks Turnkey!