JSF custom converter for date - is it thread safe?

I created a custom Converter in JSF 1.2 to convert Date objects. Dates have a special format. I executed my converter using the Java core SimpleDateFormat class to perform the conversion using the format string shown in my code comments below. All of this works great.

My question is thread safety. The SimpleDateFormat API docs state that it is not thread safe. For this reason, I created a separate instance of the date format object for each instance of my converter object. However, I am not sure if this is enough. My DateFormat object DateFormat saved as a member of the DTGDateConverter .

QUESTION: Will two threads access the same instance of the converter object in JSF at the same time?

If the answer is yes, then my converter is at risk.

 /** * <p>JSF Converter used to convert from java.util.Date to a string. * The SimpleDateFormat format used is: ddHHmm'Z'MMMyy.</p> * * <p>Example: October 31st 2010 at 23:59 formats to 312359ZOCT10</p> * * @author JTOUGH */ public class DTGDateConverter implements Converter { private static final Logger logger = LoggerFactory.getLogger(DTGDateConverter.class); private static final String EMPTY_STRING = ""; private static final DateFormat DTG_DATE_FORMAT = MyFormatterUtilities.createDTGInstance(); // The 'format' family of core Java classes are NOT thread-safe. // Each instance of this class needs its own DateFormat object or // runs the risk of two request threads accessing it at the same time. private final DateFormat df = (DateFormat)DTG_DATE_FORMAT.clone(); @Override public Object getAsObject( FacesContext context, UIComponent component, String stringValue) throws ConverterException { Date date = null; // Prevent ParseException when an empty form field is submitted // for conversion if (stringValue == null || stringValue.equals(EMPTY_STRING)) { date = null; } else { try { date = df.parse(stringValue); } catch (ParseException e) { if (logger.isDebugEnabled()) { logger.debug("Unable to convert string to Date object", e); } date = null; } } return date; } @Override public String getAsString( FacesContext context, UIComponent component, Object objectValue) throws ConverterException { if (objectValue == null) { return null; } else if (!(objectValue instanceof Date)) { throw new IllegalArgumentException( "objectValue is not a Date object"); } else { // Use 'toUpperCase()' to fix mixed case string returned // from 'MMM' portion of date format return df.format(objectValue).toUpperCase(); } } } 
+4
source share
2 answers

Will two threads access the same instance of the converter object in JSF at the same time?

Depending on how you use the converter. If you use

 <h:inputWhatever> <f:converter converterId="converterId" /> </h:inputWhatever> 

then a new instance will be created for each input element in the view, which is thread safe (expect from a very rare case of the edge when enduser has two identical views on two browser tabs in one session and at the same time returns a postback to both views).

If you use

 <h:inputWhatever converter="#{applicationBean.converter}" /> 

then the same instance will be shared in all representations of the entire application, which, therefore, is not thread safe.

However, you clone a static instance of DataFormat every time you create a converter. This part is no longer thread safe. You may risk that you are cloning an instance, and its internal state has been changed because it was used elsewhere. In addition, cloning an existing instance is not necessarily cheaper than creating a new instance.

I would recommend just declaring it threadlocal (i.e. inside the method block), regardless of how you use the converter. If the costly creation of DateFormat every time is a serious problem (are you his profile?), Then consider replacing it with JodaTime .

+7
source

Date formats are not synchronized. It is recommended to create separate for each stream. If multiple threads access the format at the same time, it must be synchronized externally.

Yes, there is no thread safety.

Put it locally in the method and create an instance for the stream

+2
source

All Articles