Пользовательский конвертер JSF для даты - Является ли потокобезопасным? - PullRequest
4 голосов
/ 13 декабря 2010

Я создал пользовательский Converter в JSF 1.2 для преобразования Date объектов.Даты имеют особый формат.Я реализовал свой конвертер, используя базовый класс Java SimpleDateFormat, чтобы выполнить преобразование, используя строку форматирования, показанную в моих комментариях к коду ниже.Это все отлично работает.

Мой вопрос касается безопасности потоков.Документация SimpleDateFormat API гласит, что она не является поточно-ориентированной.По этой причине я создал отдельный экземпляр объекта формата даты для каждого экземпляра моего объекта конвертера.Однако я не уверен, что этого достаточно.Мой DateFormat объект хранится как член DTGDateConverter.

. ВОПРОС: Будет ли два потока каждый одновременно получать доступ к одному и тому же экземпляру объекта Converter в JSF?

Если ответ да, то мой Конвертер, вероятно, находится под угрозой.

/**
 * <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();
        }
    }

}

Ответы [ 2 ]

7 голосов
/ 13 декабря 2010

Будет ли каждый из двух потоков одновременно обращаться к одному и тому же экземпляру объекта Converter в JSF?

Зависит от того, как вы используете конвертер.Если вы используете

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

, то для каждого входного элемента будет создан новый экземпляр, который является потокобезопасным (за исключением очень редкого случая, когда у конечного пользователя два идентичных представления на двух вкладках браузера водин и тот же сеанс и одновременно выполняет обратную передачу для обоих представлений).

Если вы, однако, используете

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

, то один и тот же экземпляр будет общим для всех представлений всего приложения, чтоне потокобезопасен.

Однако вы клонируете статический экземпляр DataFormat при каждом создании конвертера.Эта часть уже не потокобезопасна.Вы можете рисковать клонированием экземпляра, когда его внутреннее состояние было изменено, поскольку оно использовалось где-то еще.Кроме того, клонирование существующего экземпляра не обязательно обходится дешевле, чем создание нового экземпляра.

Я бы порекомендовал просто объявить его threadlocal (т.е. внутри блока метода), независимо от того, как вы используете конвертер.Если дороговизна создания DateFormat каждый раз является серьезной проблемой (вы ее профилировали?), То подумайте о замене на JodaTime .

2 голосов
/ 13 декабря 2010

Форматы даты не синхронизированы.Рекомендуется создавать отдельные экземпляры формата для каждого потока.Если несколько потоков обращаются к формату одновременно, он должен быть синхронизирован извне.

Да, это не потокобезопасно здесь.

Поместите его локально в метод и создайте экземпляр для потока

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...