31

I have a form field that should be converted to a Date object, as follows:

<form:input path="date" />

But I want to get a null value when this field is empty, instead of that I receive:

Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'date';
org.springframework.core.convert.ConversionFailedException: Unable to convert value "" from type 'java.lang.String' to type 'java.util.Date';

Is there an easy way to indicate that empty Strings should be converted to null? Or should I write my own PropertyEditor?

Thanks!

3
  • How can it work for non-empty strings if you didn't register a custom PropertyEditor? Commented Jan 26, 2011 at 16:15
  • Because Spring has a number of built in PropertyEditors, as in: static.springsource.org/spring/docs/3.0.3.RELEASE/… Commented Jan 27, 2011 at 12:47
  • Also says that the CustomDateEditor is NOT registered by default, but it seems that indeed it is! Commented Jan 27, 2011 at 13:23

3 Answers 3

51

Spring provides a PropertyEditor named CustomDateEditor which you can configure to convert an empty String to a null value. You typically have to register it in a @InitBinder method of your controller:

@InitBinder
public void initBinder(WebDataBinder binder) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    dateFormat.setLenient(false);

    // true passed to CustomDateEditor constructor means convert empty String to null
    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
Sign up to request clarification or add additional context in comments.

Comments

6

More recent versions of the Spring framework introduced conversion and formatting services to take care of these tasks, somehow leaving the property editors system behind. However, the issue reported is unfortunately still present: the default DateFormatter is unable to properly convert an empty string to a null Date object. What I find extremely irritating is that the Spring documentation contains a date formatter snippet example where the proper guard clauses are implemented for both conversions (to and from strings). This discrepancy between the framework implementation and the framework documentation really drives me insane, so much that I could even try to submit a patch as soon as I find some time to devote to the task.

In the meantime, my suggestion to everyone encountering this problem while using a modern version of the Spring framework is to subclass the default DateFormatter and override its parse method (its print method, too, if it's needed) so as to add a guard clause in the fashion of the one shown in the documentation.

package com.example.util;

import java.text.ParseException;
import java.util.Date;
import java.util.Locale;

public class DateFormatter extends org.springframework.format.datetime.DateFormatter {

    @Override
    public Date parse(String text, Locale locale) throws ParseException {
        if (text != null && text.isEmpty()) {
            return null;
        }
        return super.parse(text, locale);
    }

}

Then, some modifications must be applied to the XML Spring configuration: a conversion service bean must be defined, and the corresponding attribute in the annotation-driven element in the mvc namespace must be properly set.

<mvc:annotation-driven conversion-service="conversionService" />
<beans:bean
    id="conversionService"
    class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <beans:property name="formatters">
        <beans:set>
            <beans:bean class="com.example.util.DateFormatter" />
        </beans:set>
    </beans:property>
</beans:bean>

To provide a specific date format, the pattern property of the DateFormatter bean must be properly set.

<beans:bean class="com.example.util.DateFormatter">
    <beans:property name="pattern" value="yyyy-MM-dd" />
</beans:bean>

3 Comments

Very useful thanks. If I were using the Java style Spring config rather than XML do you know how to accomplish this?
@Luke unfortunately, I don't. I have yet to use Java-based configuration in a Spring project.
Ok thanks, seems most of the stuff around the net for Spring MVC and Spring Webflow config is XML style (even the docs) :)
0

Using Spring 5, this error can still happen quite erroneously.... ....if you have a mapped collection, for example like this, make sure your index is correct within the collect (this from @initBinder in Spring Controller)

if(sm != null && sm.getSapSaleItems() != null) {
        int i = sm.getSapSaleItems().size();
        for (int x = 0; x < i ; x++) {
            binder.registerCustomEditor(Date.class, "salesOrderItems[" + i + "].pickDate",
                    new CustomDateEditor(dateFormatter, true));
            
        }

"i" should be x ))), creates same error that empty string can not be cast to date:

default message [salesOrderItems[1].pickDate]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'salesOrderItems[1].pickDate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value ''; nested exception is java.lang.IllegalArgumentException]

jsp code would be like:

<td><form:input cssClass="datepicker" size="10"
                                    path="salesOrderItems[${loopStatus.index}].pickDate" /></td>

...and another reason, same configuration, that you can get this same misleading error, is if the nested collection of sap lines (see my example) is not available in the form backing object....

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.