« Velocity and Spring Web MVC | Main | HP SWF Decompiling and Security Analysis Tool »

SimpleDateFormat is not thread safe

It has always felt counter intuitive that there are classes which are not thread safe in the Sun JDK, but that is the case. One that I frequently see people trip up on is SimpleDateFormat. From the documentation:

Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

UPDATE

While SimpleDateFormat is not thread safe, as pointed out in the comments below, Spring seems to create new binders per request removing the need for this approach. In reviewing the documentation it isn't immediately clear that this is the case.

I recently had to create a custom editor for a Spring Web MVC command and ran into this issue. One possible fix, without introducing a ThreadLocal, is to just create a SimpleDateFormat every time. Hence this simple ThreadSafeSimpleDateFormat wrapper.

import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadSafeSimpleDateFormat extends DateFormat {
    private String pattern;
    
    public ThreadSafeSimpleDateFormat(String pattern) {
        this.pattern = pattern;
    }
    
    @Override
    public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
        return new SimpleDateFormat(pattern).format(date, toAppendTo, fieldPosition);
    }
    
    @Override
    public Date parse(String source, ParsePosition pos) {
        return new SimpleDateFormat(pattern).parse(source, pos);
    }
}

Then to setup that as the editor handler for a command that has a date field, in my controller that uses the command I added the following:

@Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
    super.initBinder(request, binder);
    binder.registerCustomEditor(Date.class, DATE_TIME, new CustomDateEditor(new ThreadSafeSimpleDateFormat(DATE_TIME_FORMAT), false));
}


Tags: date java spring

Comments

It always amazes me what a giant mess the Java API (and its myriad, overlapping, often incompatible, tacked-on bits of functionality provided by Sun, Apache, etc.) is. I have to develop in both C#/.NET and Java for work, and I wish I could just ditch Java. 1.6 is a touch better than 1.5, but still...
Mmmmh, it seems that it is not necessary at all because Spring ensure that the initBinder is called for each request. See this thread: http://forum.springframework.org/showthread.php?t=24389

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)



About