Registering Property Editors in Spring

I could not get this to work…

Problem

A property editor is a feature of the JavaBeans API for converting property values to and from text values. Each property editor is designed for a certain type of property only. You may wish to employ property editors to simplify your bean configurations.

Solution

The Spring IoC container supports using property editors to help with bean configurations. For example, with a property editor for the java.net.URL type, you can specify a URL string for a property of the URL type. Spring will automatically convert the URL string into a URL object and inject it into your property. Spring comes with several property editors for converting bean properties of common types.

Typically, you should register a property editor in the Spring IoC container before it can be used. The CustomEditorConfigurer is implemented as a bean factory post processor for you to register your custom property editors before any of the beans get instantiated.

How It Works

As an example, suppose you would like your product ranking to be based on sales for a particular period. For this change, you add the fromDate and toDate properties to your ProductRanking class.

package com.apress.springrecipes.shop;
public class ProductRanking {
private Product bestSeller;
private Date fromDate;
private Date toDate;
// Getters and Setters
}

To specify the value for a java.util.Date property in a Java program, you can convert it from a date string of particular pattern with the help of the DateFormat.parse() method.

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
productRanking.setFromDate(dateFormat.parse("2007-09-01"));
productRanking.setToDate(dateFormat.parse("2007-09-30"));

To write the equivalent bean configuration in Spring, you first declare a dateFormat bean with the pattern configured. As the parse() method is called for converting the date strings into date objects, you can consider it as an instance factory method to create the date beans.

<beans …>
<bean id="dateFormat" class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-MM-dd" />
</bean>
<bean id="productRanking"
class="com.apress.springrecipes.shop.ProductRanking">
<property name="bestSeller">
<bean class="com.apress.springrecipes.shop.Disc">
<property name="name" value="CD-RW" />
<property name="price" value="1.5" />
</bean>
</property>
<property name="fromDate">
<bean factory-bean="dateFormat" factory-method="parse">
<constructor-arg value="2007-09-01" />
</bean>
</property>
<property name="toDate">
<bean factory-bean="dateFormat" factory-method="parse">
<constructor-arg value="2007-09-30" />
</bean>
</property>
</bean>
</beans>

As you can see, the preceding configuration is too complicated for setting date properties. Actually, the Spring IoC container is able to convert the text values for your properties by using property editors. The CustomDateEditor class that comes with Spring is for converting date strings into java.util.Date properties. First, you have to declare an instance of it in the bean configuration file.

<beans …>
<bean id="dateEditor"
class="org.springframework.beans.propertyeditors.CustomDateEditor">
<constructor-arg>
<bean class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-MM-dd" />
</bean>
</constructor-arg>
<constructor-arg value="true" />
</bean>
</beans>

This editor requires a DateFormat object as the first constructor argument. The second argument indicates whether this editor allows empty values. Next you have to register this property editor in a CustomEditorConfigurer instance so that Spring can convert properties whose type is java.util.Date. Now you can specify a date value in text format for any java.util.Date properties:

<beans …>
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.util.Date">
<ref local="dateEditor" />
</entry>
</map>
</property>
</bean>
<bean id="productRanking"
class="com.apress.springrecipes.shop.ProductRanking">
<property name="bestSeller">
<bean class="com.apress.springrecipes.shop.Disc">
<property name="name" value="CD-RW" />
<property name="price" value="1.5" />
</bean>
</property>
<property name="fromDate" value="2007-09-01" />
<property name="toDate" value="2007-09-30" />
</bean>
</beans>

You can test whether your CustomDateEditor configuration works with the following Main class:

package com.apress.springrecipes.shop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) throws Exception {
ApplicationContext context =
new ClassPathXmlApplicationContext("beans.xml");
ProductRanking productRanking =
(ProductRanking) context.getBean("productRanking");
System.out.println("Product ranking from " + productRanking.getFromDate() + " to " + productRanking.getToDate());
}
}

In addition to CustomDateEditor, Spring comes with several property editors for converting common data types, such as CustomNumberEditor, ClassEditor, FileEditor, LocaleEditor, StringArrayPropertyEditor, and URLEditor. Among them, ClassEditor, FileEditor, LocaleEditor, and URLEditor are preregistered by Spring, so you don’t need to register them again. For more information on using these editors, you can consult the javadoc of these classes in the org.springframework.beans.propertyeditors package.