Close

Spring - The Use Of PropertyEditors With XML Configuration

[Last Updated: Dec 22, 2023]

This tutorial shows how property editors are used when XML configuration is used to initialize beans.

When XML configuration is used, setting properties on beans is done by using PropertyEditor implementations. When we use String as the value of a property of some bean that we declare in an XML file, Spring uses an appropriate PropertyEditor to convert String to the target type.

Examples

Use of default PropertyEditors

src/main/resources/spring-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="customer" class="com.logicbig.example.XmlConfigExample.Order">
        <property name="amount" value="102"/>
        <property name="currency" value="USD"/>
    </bean>
</beans>

spring-property-editors-used-with-xml-config/src/main/java/com/logicbig/example/XmlConfigExample.java

package com.logicbig.example;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Currency;

public class XmlConfigExample {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        Order order = context.getBean(Order.class);
        System.out.println(order);
        System.out.println("Currency symbol: "+order.getCurrency().getSymbol());
        System.out.println("Currency display name: "+order.getCurrency().getDisplayName());
    }

    static class Order{
      private double amount;
      private Currency currency;

        public double getAmount() {
            return amount;
        }

        public void setAmount(double amount) {
            this.amount = amount;
        }

        public Currency getCurrency() {
            return currency;
        }

        public void setCurrency(Currency currency) {
            this.currency = currency;
        }

        @Override
        public String toString() {
            return "Order{" +
                    "amount=" + amount +
                    ", currency=" + currency +
                    '}';
        }
    }
}

Output

Order{amount=102.0, currency=USD}
Currency symbol: $
Currency display name: US Dollar

Using Custom PropertyEditor

src/main/resources/spring-config2.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="customer" class="com.logicbig.example.XmlCustomEditorExample.MyBean">
        <property name="price" value="45,678.567"/>
    </bean>

    <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="propertyEditorRegistrars">
            <list>
                <bean class="com.logicbig.example.XmlCustomEditorExample.MyCustomEditorRegistrar" />
            </list>
        </property>
    </bean>
</beans>

As seen above, we registered CustomEditorConfigurer as a bean. This allows for convenient registration of custom property editors via it's propertyEditorRegistrars property. In this example our implementation of PropertyEditorRegistrar (MyCustomEditorRegistrar) is going to register CustomNumberEditor with a custom number format.

spring-property-editors-used-with-xml-config/src/main/java/com/logicbig/example/XmlCustomEditorExample.java

package com.logicbig.example;

import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.propertyeditors.CustomNumberEditor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.text.DecimalFormat;
import java.text.NumberFormat;

public class XmlCustomEditorExample {

    public static void main (String[] args) {
        ApplicationContext context = new
                            ClassPathXmlApplicationContext("spring-config2.xml");
        MyBean bean = context.getBean(MyBean.class);
        System.out.println(bean);
    }

    public static class MyBean {
        private Double price;

        public Double getPrice () {
            return price;
        }

        public void setPrice (Double price) {
            this.price = price;
        }

        @Override
        public String toString () {
            return "MyBean{" + "price=" + price + '}';
        }
    }

    public static class MyCustomEditorRegistrar implements PropertyEditorRegistrar {
        @Override
        public void registerCustomEditors (PropertyEditorRegistry registry) {
            NumberFormat numberFormat = new DecimalFormat("##,###.00");
            registry.registerCustomEditor(java.lang.Double.class,
                                          new CustomNumberEditor(java.lang.Double.class,
                                                                 numberFormat, true));
        }
    }
}

Output

MyBean{price=45678.567}

Creating a new PropertyEditor

src/main/resources/spring-config3.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="customer" class="com.logicbig.example.XmlNewEditorExample.Customer">
        <property name="customerName" value="Steve Thomas"/>
        <property name="phone" value="cell | 907-111-2123"/>
    </bean>

    <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="customEditors">
            <map>
                <entry key="com.logicbig.example.XmlNewEditorExample$Phone"
                       value="com.logicbig.example.XmlNewEditorExample$CustomPhoneEditor"/>
            </map>
        </property>
    </bean>
</beans>
package com.logicbig.example;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.beans.PropertyEditorSupport;

public class XmlNewEditorExample {

    public static void main (String[] args) {
        ApplicationContext context = new
                            ClassPathXmlApplicationContext("spring-config3.xml");
        Customer bean = context.getBean(Customer.class);
        System.out.println(bean);
    }

    public static class Customer {
        private String customerName;
        private Phone phone;

        public String getCustomerName () {
            return customerName;
        }

        public void setCustomerName (String customerName) {
            this.customerName = customerName;
        }

        public Phone getPhone () {
            return phone;
        }

        public void setPhone (Phone phone) {
            this.phone = phone;
        }

        @Override
        public String toString () {
            return "Customer{" +
                                "customerName='" + customerName + '\'' +
                                ", phone=" + phone +
                                '}';
        }
    }

    public static class Phone {
        private String phoneNumber;
        private PhoneType phoneType;

        public String getPhoneNumber () {
            return phoneNumber;
        }

        public void setPhoneNumber (String phoneNumber) {
            this.phoneNumber = phoneNumber;
        }

        public PhoneType getPhoneType () {
            return phoneType;
        }

        public void setPhoneType (PhoneType phoneType) {
            this.phoneType = phoneType;
        }

        @Override
        public String toString () {
            return "Phone{" +
                                "phoneNumber='" + phoneNumber + '\'' +
                                ", phoneType=" + phoneType +
                                '}';
        }
    }

    public static enum PhoneType {
        LAND,
        CELL,
        WORK
    }

    public static class CustomPhoneEditor extends PropertyEditorSupport {

        @Override
        public void setAsText (String text) throws IllegalArgumentException {
            String[] split = text.split("[|]");
            if (split.length != 2) {
                throw new IllegalArgumentException(
                                    "Phone is not correctly defined. The correct format is " +
                                                        "PhoneType|111-111-1111");
            }

            PhoneType phoneType = PhoneType.valueOf(split[0].trim()
                                                            .toUpperCase());
            Phone phone = new Phone();
            phone.setPhoneType(phoneType);
            phone.setPhoneNumber(split[1].trim());
            setValue(phone);

        }
    }
}

Output

Customer{customerName='Steve Thomas', phone=Phone{phoneNumber='907-111-2123', phoneType=CELL}}

In above example we registered PropertyEditor classes via the CustomEditorConfigurer#customEditors property (as opposed to the last example where we used CustomEditorConfigurer#propertyEditorRegistrars). When using customEditors property, Spring will create fresh instances of the specified editor class for each editing attempt. In case we need control over the instantiation process of PropertyEditors, use a PropertyEditorRegistrar to register them. (last example)

Following example shows creating and registering new editor via CustomEditorConfigurer#propertyEditorRegistrars

src/main/resources/spring-config4.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="customer" class="com.logicbig.example.XmlNewEditorExample.Customer">
        <property name="customerName" value="Steve Thomas"/>
        <property name="phone" value="cell | 907-111-2123"/>
    </bean>

    <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="propertyEditorRegistrars">
            <list>
                <bean class="com.logicbig.example.XmlNewEditorExample2.MyCustomEditorRegistrar" />
            </list>
        </property>
  </bean>
</beans>
package com.logicbig.example;

import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class XmlNewEditorExample2 {

    public static void main(String[] args) {
        ApplicationContext context = new
                ClassPathXmlApplicationContext("spring-config4.xml");
        XmlNewEditorExample.Customer bean = context.getBean(XmlNewEditorExample.Customer.class);
        System.out.println(bean);
    }

    public static class MyCustomEditorRegistrar implements PropertyEditorRegistrar {

        @Override
        public void registerCustomEditors(PropertyEditorRegistry propertyEditorRegistry) {
            propertyEditorRegistry.registerCustomEditor(
                    XmlNewEditorExample.Phone.class, "phone", new XmlNewEditorExample.CustomPhoneEditor());
        }
    }
}

Output

Customer{customerName='Steve Thomas', phone=Phone{phoneNumber='907-111-2123', phoneType=CELL}}

Example Project

Dependencies and Technologies Used:

  • spring-context 6.1.2 (Spring Context)
     Version Compatibility: 3.2.3.RELEASE - 6.1.2Version List
    ×

    Version compatibilities of spring-context with this example:

    • 3.2.3.RELEASE
    • 3.2.4.RELEASE
    • 3.2.5.RELEASE
    • 3.2.6.RELEASE
    • 3.2.7.RELEASE
    • 3.2.8.RELEASE
    • 3.2.9.RELEASE
    • 3.2.10.RELEASE
    • 3.2.11.RELEASE
    • 3.2.12.RELEASE
    • 3.2.13.RELEASE
    • 3.2.14.RELEASE
    • 3.2.15.RELEASE
    • 3.2.16.RELEASE
    • 3.2.17.RELEASE
    • 3.2.18.RELEASE
    • 4.0.0.RELEASE
    • 4.0.1.RELEASE
    • 4.0.2.RELEASE
    • 4.0.3.RELEASE
    • 4.0.4.RELEASE
    • 4.0.5.RELEASE
    • 4.0.6.RELEASE
    • 4.0.7.RELEASE
    • 4.0.8.RELEASE
    • 4.0.9.RELEASE
    • 4.1.0.RELEASE
    • 4.1.1.RELEASE
    • 4.1.2.RELEASE
    • 4.1.3.RELEASE
    • 4.1.4.RELEASE
    • 4.1.5.RELEASE
    • 4.1.6.RELEASE
    • 4.1.7.RELEASE
    • 4.1.8.RELEASE
    • 4.1.9.RELEASE
    • 4.2.0.RELEASE
    • 4.2.1.RELEASE
    • 4.2.2.RELEASE
    • 4.2.3.RELEASE
    • 4.2.4.RELEASE
    • 4.2.5.RELEASE
    • 4.2.6.RELEASE
    • 4.2.7.RELEASE
    • 4.2.8.RELEASE
    • 4.2.9.RELEASE
    • 4.3.0.RELEASE
    • 4.3.1.RELEASE
    • 4.3.2.RELEASE
    • 4.3.3.RELEASE
    • 4.3.4.RELEASE
    • 4.3.5.RELEASE
    • 4.3.6.RELEASE
    • 4.3.7.RELEASE
    • 4.3.8.RELEASE
    • 4.3.9.RELEASE
    • 4.3.10.RELEASE
    • 4.3.11.RELEASE
    • 4.3.12.RELEASE
    • 4.3.13.RELEASE
    • 4.3.14.RELEASE
    • 4.3.15.RELEASE
    • 4.3.16.RELEASE
    • 4.3.17.RELEASE
    • 4.3.18.RELEASE
    • 4.3.19.RELEASE
    • 4.3.20.RELEASE
    • 4.3.21.RELEASE
    • 4.3.22.RELEASE
    • 4.3.23.RELEASE
    • 4.3.24.RELEASE
    • 4.3.25.RELEASE
    • 4.3.26.RELEASE
    • 4.3.27.RELEASE
    • 4.3.28.RELEASE
    • 4.3.29.RELEASE
    • 4.3.30.RELEASE
    • 5.0.0.RELEASE
    • 5.0.1.RELEASE
    • 5.0.2.RELEASE
    • 5.0.3.RELEASE
    • 5.0.4.RELEASE
    • 5.0.5.RELEASE
    • 5.0.6.RELEASE
    • 5.0.7.RELEASE
    • 5.0.8.RELEASE
    • 5.0.9.RELEASE
    • 5.0.10.RELEASE
    • 5.0.11.RELEASE
    • 5.0.12.RELEASE
    • 5.0.13.RELEASE
    • 5.0.14.RELEASE
    • 5.0.15.RELEASE
    • 5.0.16.RELEASE
    • 5.0.17.RELEASE
    • 5.0.18.RELEASE
    • 5.0.19.RELEASE
    • 5.0.20.RELEASE
    • 5.1.0.RELEASE
    • 5.1.1.RELEASE
    • 5.1.2.RELEASE
    • 5.1.3.RELEASE
    • 5.1.4.RELEASE
    • 5.1.5.RELEASE
    • 5.1.6.RELEASE
    • 5.1.7.RELEASE
    • 5.1.8.RELEASE
    • 5.1.9.RELEASE
    • 5.1.10.RELEASE
    • 5.1.11.RELEASE
    • 5.1.12.RELEASE
    • 5.1.13.RELEASE
    • 5.1.14.RELEASE
    • 5.1.15.RELEASE
    • 5.1.16.RELEASE
    • 5.1.17.RELEASE
    • 5.1.18.RELEASE
    • 5.1.19.RELEASE
    • 5.1.20.RELEASE
    • 5.2.0.RELEASE
    • 5.2.1.RELEASE
    • 5.2.2.RELEASE
    • 5.2.3.RELEASE
    • 5.2.4.RELEASE
    • 5.2.5.RELEASE
    • 5.2.6.RELEASE
    • 5.2.7.RELEASE
    • 5.2.8.RELEASE
    • 5.2.9.RELEASE
    • 5.2.10.RELEASE
    • 5.2.11.RELEASE
    • 5.2.12.RELEASE
    • 5.2.13.RELEASE
    • 5.2.14.RELEASE
    • 5.2.15.RELEASE
    • 5.2.16.RELEASE
    • 5.2.17.RELEASE
    • 5.2.18.RELEASE
    • 5.2.19.RELEASE
    • 5.2.20.RELEASE
    • 5.2.21.RELEASE
    • 5.2.22.RELEASE
    • 5.2.23.RELEASE
    • 5.2.24.RELEASE
    • 5.2.25.RELEASE
    • 5.3.0
    • 5.3.1
    • 5.3.2
    • 5.3.3
    • 5.3.4
    • 5.3.5
    • 5.3.6
    • 5.3.7
    • 5.3.8
    • 5.3.9
    • 5.3.10
    • 5.3.11
    • 5.3.12
    • 5.3.13
    • 5.3.14
    • 5.3.15
    • 5.3.16
    • 5.3.17
    • 5.3.18
    • 5.3.19
    • 5.3.20
    • 5.3.21
    • 5.3.22
    • 5.3.23
    • 5.3.24
    • 5.3.25
    • 5.3.26
    • 5.3.27
    • 5.3.28
    • 5.3.29
    • 5.3.30
    • 5.3.31
    • Compatible Java Version: 17+
    • 6.0.0
    • 6.0.1
    • 6.0.2
    • 6.0.3
    • 6.0.4
    • 6.0.5
    • 6.0.6
    • 6.0.7
    • 6.0.8
    • 6.0.9
    • 6.0.10
    • 6.0.11
    • 6.0.12
    • 6.0.13
    • 6.0.14
    • 6.0.15
    • 6.1.0
    • 6.1.1
    • 6.1.2

    Versions in green have been tested.

  • JDK 17
  • Maven 3.8.1

Spring - Use of PropertyEditors With XML Configuration Select All Download
  • spring-property-editors-used-with-xml-config
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • XmlNewEditorExample.java
          • resources

    See Also