Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

Code Block
protected IConverterLocator newConverterLocator() {
    ConverterLocator converterLocator = new ConverterLocator();
    converterLocator.set(Money.class, new MoneyConverter());
    return converterLocator;
}

In Wicket 1.4

This is the same as in 1.3.

My customers do not know what a "Double" is, so the message "'value' is not a valid Double" doesn't make sense. I wanted to provide a simpler message.

Custom message for class Double

First, as with other converters, you override newConverterLocator in your application.

Code Block
titleApplication.java

public class Application extends WebApplication {
...
    @Override
    protected IConverterLocator newConverterLocator() {
        ConverterLocator locator = (ConverterLocator) super.newConverterLocator();
        locator.set(Double.class, new MyDoubleConverter());
        return locator;
    }
    ....

This tells Wicket for the Double class, use MyDoubleConverter for converting, which also takes care of reporting the error when not parsable. It seems the only reason I need to create MyDoubleConverter is for variable substitution in my message. (There doesn't seem to be a default key for the value. For the class, it looks like you can use "type" although I didn't try it.)

Code Block
titleApplication.java

// This is an inner class within my Application
private static final class MyDoubleConverter extends DoubleConverter {
    private static final long serialVersionUID = 1L;

    @Override
    protected ConversionException newConversionException(String message, Object value,
            Locale locale) {
        final ConversionException newConversionException = super.newConversionException(message, value, locale);
        newConversionException.setVariable("value", value);
        return newConversionException;
    }
}

I tried implementing it as an anonymous class, but got a java.io.NotSerializableException. Once I moved this to an inner class it worked. If you know why, let me know!

The final piece of the puzzle is to put the message in your properties file. I put it in my BasePage.properties file.

Code Block
titleBasePage.properties

IConverter.Double='${value}' is not a valid number

Providing a custom converter for specific components

...

Code Block
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;

import wicket.util.convert.ConversionException;
import wicket.util.convert.IConverter;

/**
 * Converts from and to URLs.
 *
 * @author Eelco Hillenius
 */
public class URLConverter implements IConverter
{
	/**
	 * Construct.
	 */
	public URLConverter()
	{
	}

	/**
	 * @see wicket.util.convert.IConverter#convertToObjectIConverter#convert(java.lang.Object, java.lang.Class)
	 */
	public Object convertToObjectconvert(Object value, Class c)
	{
		if (value == null)
		{
			return null;
		}

		if (c == URL.class)
		{
			if (value.getClass() == URL.class)
			{
				return value;
			}

			try
			{
				return new URL(value.toString());
			}
			catch (MalformedURLException e)
			{
				throw new ConversionException("'" + value + "' is not a valid URL");
			}
		}
		return value.toString();
	}

	/**
	 * @see wicket.util.convert.ILocalizable#setLocale(java.util.Locale)
	 */
	public void setLocale(Locale locale)
	{
	}

	/**
	 * @see wicket.util.convert.ILocalizable#getLocale()
	 */
	public Locale getLocale()
	{
		return Locale.getDefault();
	}
}

...

Note that we used the converter of the most generic type, wicket.util.convert.IConverter. If you use this type, you have to look at the requested target type (thus you code like: if(c.equals(URL.class))) yourself. While using wicket.util.convert.Converter is easier, as in that case you can couple {{wicket.util.convert.ITypeConverter}} s, using IConverter directly is transparent (easier to debug) and it forces to do only one type of conversion.