December 12th, 2009 by roger
About four years ago, we switched our office phone system from a proprietary ISDN PBX to Asterisk with Cisco 7940 handsets. It was an instant success and has been running without interruption ever since. It routes incoming faxes to email, provides voicemail, soft-phones and conference rooms, allows us to take our extensions with us wherever we are in the world, provides us with unlimited incoming and outgoing lines over SIP gateways and all the other amazing stuff which Asterisk provides. It was Asterisk which first made me realize that open-source systems can be a whole lot better than closed-source – especially in the proprietary world of telephony.
The only thing which bothered me about our Asterisk PBX was that it was running on a Dell server equipped with a rather obscure Junghanns quad-port ISDN board. It worried me that if either the server or the board died, it would take us quite some time to restore service.
What I really wanted was Asterisk running as a virtual machine, so I could back it up like all our other VMs and move it around within our network infrastructure as needed. Up until now, this wasn’t practical because of high resolution timer issues with the conferencing features. Finally, with the newest Asterisk versions (we’re using the latest beta of version 1.6.2) running on the newest Linux kernels (Debian), its feasible to run it as a VM.
So, as of today, we have our Asterisk PBX virtualized – no moving parts. It connects to our ISDN lines via a Voxtream Parlay voXip gateway. We’re running it on VMWare server 1.0.10 on a dual quad-core Xeon 5420 server with 12GB RAM (the server is running plenty of other VMs alongside the Asterisk VM) . It uses a scarcely noticeable amount of CPU during regular telephony where Asterisk is just connecting SIP end-points. Only conference-rooms, where the Asterisk server is transcoding multiple streams of voip traffic, actually require much CPU resources. Even there, based on our tests, we don’t expect any significant burden on the server.
Tags: Asterisk, telephony, virtualization, VMWare, voip
Posted in Other | No Comments »
November 30th, 2009 by roger
Our first approach was to create a DefaultFocusBehavior (as described by Julian Sinai) and attach it to the component which should receive the focus. The problem with this is that after a validation error during a submit, you usually want the focus to jump to the first invalid field, so the user can easily correct his erroneous input. The problem with the DefaultFocusBehavior is that the component to which you added it still has it and will try to grab the focus again. We created two methods for handling focus in our BasePage class (from which all of our application pages are inherited) – setFocus and setFocusToFirstInvalidComponent. The first one is called during page initialization and the second on validation failure. They share enough class variables which allow them to ensure that only one component has the DefaultFocusBehavior at a time.
Tags: focus, Wicket
Posted in Java | No Comments »
November 27th, 2009 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:
String getStringWithParameters(String id, Object... args) {
return getString(id, new Model<Object[]>(args));
}
This method takes your varargs and creates an object array which the standard getString function can use to look up your parameters by index.
Posted in Other | No Comments »
November 25th, 2009 by roger
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.
Tags: Wicket
Posted in Other | No Comments »
November 20th, 2009 by roger
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.
Here’s the overload of the newLink method:
tabPanel = new TabbedPanel("tabs", tabs) {
private static final long serialVersionUID = 1L;
@Override
protected WebMarkupContainer newLink(String linkId, final int index) {
Form form = ((AbstractTabWithForm) tabs.get(getSelectedTab())).getForm();
if (form != null) {
return new AjaxSubmitLink(linkId, form) {
private static final long serialVersionUID = 1L;
@Override
protected void onError(AjaxRequestTarget target, Form form) {
super.onError(target, form);
target.addComponent(tabPanel);
}
@Override
protected void onSubmit(AjaxRequestTarget target, Form form) {
setSelectedTab(index);
if (target != null) {
target.addComponent(tabPanel);
}
}
};
} else {
return super.newLink(linkId, index);
}
}
};
tabPanel.setOutputMarkupId(true);
add(tabPanel);
Here’s the subclass of the AbstractTab to provide access to the form:
abstract class AbstractTabWithForm extends AbstractTab {
private static final long serialVersionUID = 1L;
public AbstractTabWithForm(IModel title) {
super(title);
}
// override this if you have a form
public Form getForm() {
return null;
}
}
Here’s how the tabs are added:
tabs.add(new AbstractTabWithForm(new Model("General")) {
private static final long serialVersionUID = 1L;
private BasePanel panel = null;
@Override
public Panel getPanel(String panelId) {
try {
if (panel == null)
panel = new GeneralPanel(panelId, item);
} catch (Exception e) {
error(e.getMessage());
}
return panel;
}
@Override
public Form getForm() {
return panel.getForm();
}
});
And here’s how it looks in practice – in the example below, the user is attempting to switch tabs before all required fields have been filled out in the current tab.

Posted in Other | 1 Comment »
October 20th, 2009 by roger
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.
class CCValidator extends AbstractFormValidator implements Serializable {
private static final long serialVersionUID = 1L;
private final TextArea<String> cc;
public CCValidator(TextArea<String> cc) {
this.cc = cc;
}
public FormComponent<?>[] getDependentFormComponents() {
return new FormComponent[] { cc };
}
public void validate(Form<?> form) {
String cc_entered = cc.getConvertedInput();
String[] ccList = cc_entered.split("\r\n");
for (String email : ccList) {
if (!isValidEmailAddress(email)) {
Map<String, Object> map = super.variablesMap();
map.put("email_address", email);
error(cc, "invalid_cc", map);
}
}
}
private boolean isValidEmailAddress(final String emailAddress) {
Validatable<String> v = new Validatable<String>(emailAddress);
EmailAddressValidator.getInstance().validate(v);
return v.isValid();
}
}
To use it, add it to the form as follows:
form.add(new CCValidator(cc));
// where cc is the TextArea where the cc list should be entered
Tags: Wicket
Posted in Java | 1 Comment »
September 12th, 2009 by roger
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:
<?xml version="1.0" encoding="ISO-8859-1"?>
<application
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.zeroturnaround.com"
xsi:schemaLocation="http://www.zeroturnaround.com/alderaan/rebel-2_0.xsd">
<classpath fallback="true">
<dir name="/Users/userx/Documents/workspace/projectx/build/classes"/>
</classpath>
</application>
where the “dir name” element is set to the directory where Eclipse writes the compiled .class files for your project.
In eclipse, you need to modify the launch configuration for tomcat and add the following to the arguments:
-noverify
-javaagent:/path/to/jrebel.jar
-Drebel.trace.log=true
-Drebel.wicket_plugin=true
Posted in Java, Other | No Comments »
September 1st, 2009 by roger
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).
Instead of:
<label for="option1">
<input id="option1" type="checkbox" wicket:id="option1"/>Option 1
</label>
use:
<label>
<input type="checkbox" wicket:id="option1"/>Option 1
</label>
Tags: html, Wicket
Posted in Java | No Comments »
August 29th, 2009 by roger
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):
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.application.IComponentOnBeforeRenderListener;
import org.apache.wicket.behavior.AbstractBehavior;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.IPropertyReflectionAwareModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.validation.validator.StringValidator;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotNull;
/**
* Configure a Wicket Component based on Hibernate annotations (@NotNull and @Length(min=x,max=y)).
*
* Inspects the Model of a FormComponent and configures the Component according to the declared Hibernate Annotations used on the model object.
* NOTE: This means the Component's Model mustbe known when configuring a Component.
*
* This object can be used as a Behavior to configure a single Component.
* NOTE: this object is stateless, and the same instance can be reused to configure multiple Components.
*
* public class MyWebPage extends WebPage {
* public MyWebPage() {
* TextField name = new TextField("id", new PropertyModel(user, "name");
* name.addBehavior(new AnnotatedConstraintBehavior());
* add(name);
* }
* }
*
* This object can also be used as a component listener that will automatically configure all FormComponents based on Hibernate annotations. This ensures that an entire application respects annotations without adding custom Validators or Behaviors to each FormComponent.
*
* public class MyApplication extends WebApplication {
* public void init() {
* addPreComponentOnBeforeRenderListener(new AnnotatedConstraintBehavior());
* }
* }
*
* @see http://jroller.com/page/wireframe/?anchor= hibernateannotationcomponentconfigurator
* @see http ://jroller.com/page/wireframe/?anchor=hibernate_annotations_and_wicket
*/
@SuppressWarnings("serial")
public class AnnotatedConstraintBehavior extends AbstractBehavior implements IComponentOnBeforeRenderListener {
@SuppressWarnings("unchecked")
private static Map configs = new HashMap() {
{
put(NotNull.class, new HibernateAnnotationConfig() {
public void onAnnotatedComponent(Annotation annotation, FormComponent component) {
component.setRequired(true);
}
});
put(Length.class, new HibernateAnnotationConfig() {
public void onAnnotatedComponent(Annotation annotation, FormComponent component) {
int max = ((Length) annotation).max();
component.add(new AttributeModifier("maxlength", true, new Model(Integer.toString(max))));
component.add(StringValidator.maximumLength(max));
}
});
}
};
@Override
public final void bind(Component component) {
super.bind(component);
configure(component);
}
public final void onBeforeRender(Component component) {
if (!component.hasBeenRendered()) {
configure(component);
}
}
void configure(Component component) {
if (!isApplicableFor(component)) {
return;
}
FormComponent formComponent = (FormComponent) component;
IPropertyReflectionAwareModel propertyModel = (IPropertyReflectionAwareModel) component.getDefaultModel();
for (Annotation annotation : getAnnotations(propertyModel)) {
Class<? extends Annotation> annotationType = annotation.annotationType();
HibernateAnnotationConfig config = (HibernateAnnotationConfig) configs.get(annotationType);
if (null != config) {
config.onAnnotatedComponent(annotation, formComponent);
}
}
}
private Collection<Annotation> getAnnotations(IPropertyReflectionAwareModel propertyModel) {
Field field = propertyModel.getPropertyField();
if (field == null) {
//Log.warn("Unable to find annotations for model: " + propertyModel);
return Collections.emptyList();
}
return Arrays.asList(field.getAnnotations());
}
private boolean isApplicableFor(Component component) {
if (!(component instanceof FormComponent)) {
return false;
}
IModel model = component.getDefaultModel();
if (null == model || !IPropertyReflectionAwareModel.class.isAssignableFrom(model.getClass())) {
//Log.warn("No valid model is available for configuring Component: " + component);
return false;
}
return true;
}
/**
* simple interface to abstract performing work for a specific annotation.
*/
private static interface HibernateAnnotationConfig {
void onAnnotatedComponent(Annotation annotation, FormComponent component);
}
}
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.
Tags: annotations, Hibernate, Wicket
Posted in Java | No Comments »
July 9th, 2009 by roger
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…).
Anyway, here’s the component:
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
public abstract class PasswordTextFieldWithStrength extends PasswordTextField {
private static final long serialVersionUID = 1L;
public abstract void onUpdate(String passwordStrength, AjaxRequestTarget target);
public PasswordTextFieldWithStrength(String id) {
super(id);
add(new OnChangeAjaxBehavior() {
private static final long serialVersionUID = 1L;
@Override
protected void onUpdate(AjaxRequestTarget target) {
String strength = getPasswordStrength(PasswordTextFieldWithStrength.this.getDefaultModelObjectAsString());
PasswordTextFieldWithStrength.this.onUpdate(strength, target);
}
});
}
public String getStrength() {
return getPasswordStrength(getDefaultModelObjectAsString());
}
private String getPasswordStrength(String password) {
if (password.isEmpty())
return "empty";
String alphaPresent = ".*\\w.*"; // at least one alpha character
String nonAlphanumericPresent = ".*[^a-zA-Z0-9].*"; // at least one non-alphanumeric character
String nonAlphaPresent = ".*[^a-zA-Z].*"; // at least one non-alpha character
if (password.matches(alphaPresent) && password.matches(nonAlphanumericPresent) && password.length() >= 7)
return "strong";
if (password.matches(alphaPresent) && password.matches(nonAlphaPresent) && password.length() >= 6)
return "medium";
return "weak";
}
}
And here’s how to use it:
// 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;
[caption id="attachment_33" align="aligncenter" width="492" caption="And here's how it looks in an application"]<img class="size-full wp-image-33" title="screenshot" src="http://blog.armstrongconsulting.com/wp-content/uploads/2009/07/Picture-31.png" alt="And here's how it looks in an application" width="492" height="234" />[/caption]
@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);
Tags: Security, Wicket
Posted in Java | No Comments »