2010-12-13 7 views
4

Dateのオブジェクトを変換するために、JSF 1.2でカスタムConverterを作成しました。日付は非常に特殊な形式です。私は変換を行うためにコアJavaのSimpleDateFormatクラスを使用して私のコンバータを実装しました。私のコードコメントに示されているフォーマッタ文字列を使っています。これはすべて正常に動作します。JSFカスタムコンバータfor日付 - スレッドセーフですか?

私の質問は、スレッドの安全性です。 SimpleDateFormat APIドキュメントでは、スレッドセーフではないことを示しています。そのため、私は、コンバータオブジェクトのインスタンスごとに日付書式オブジェクトの別のインスタンスを作成しました。しかし、これで十分か分かりません。私のDateFormatオブジェクトは、DTGDateConverterのメンバーとして格納されています。

質問:2つのスレッドが同時にJSF内のConverterオブジェクトの同じインスタンスにアクセスしますか?

答えが「はい」の場合、私のコンバータはおそらく危険にさらされています。

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

} 
+0

balusC?!あなたはどこですか? – mkoryak

+2

@mkoryak:私も仕事と人生を共にしています:) – BalusC

+0

111K rep、thatsすべて私は言っています:) – mkoryak

答えて

7

れる2つのスレッドをその地域の方法に入れて、スレッドごとにインスタンスを作成しますか?

コンバーターの使い方によって異なります。あなたは

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

を使用する場合は、新しいインスタンスは、エンドユーザーが同じセッションで2つのブラウザタブに二つの同一のビューを持っている非常にまれなエッジ例期待スレッドセーフであるビュー内のすべての入力要素、(作成されます両方のビューで同時にポストバックを発行します)。

あなたはしかし

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

を使用する場合は、同じインスタンスは、このようにスレッドセーフではありません、アプリケーション全体のすべてのビュー間で共有されます。

ただし、コンバータを作成するたびに静的なDataFormatインスタンスを複製しています。その部分はすでにスレッドセーフではありません。インスタンスが他の場所で使用されているため、内部状態が変更されている間にインスタンスをクローンする危険性があります。また、既存のインスタンスのクローン作成は、新しいインスタンスの作成よりも必ずしも安価ではありません。

どのようにコンバータを使用するかに関係なく、threadlocal(つまりメソッドブロック内)を宣言することをお勧めします。毎回DateFormatを作成することの費用が重大な問題である場合は、それをJodaTimeに置き換えることを検討してください。

+0

私はとして私のfaces-config.xmlで宣言しており、最初のシナリオで示したようにconverter-idで参照されます。私はそれをプロファイリングしていないので、あなたはそこで良い点を作っています。ありがとう! –

2

日付フォーマットは同期されません。各スレッドに対して個別の 形式のインスタンスを作成するには、 を推奨します。 複数のスレッドが同時にフォーマット にアクセスする場合は、外部で を同期させる必要があります。

はい、スレッドセーフではありません。

は、すべて同時にJSFにおけるコンバータオブジェクトの同じインスタンスにアクセス

+0

JSF Converterインスタンスは複数のスレッドで同時にアクセスされていると言っていますか? –

+0

@Jimそれは第2のポイントですが、まず、静的な 'DateFormat'のオブジェクトを複製しています。このオブジェクトは、どのような要求でもオブジェクトの状態をコピーします。 –

+0

私がしようとしているのは、作成されたDateFormatオブジェクトの数を最小限に抑えること、またはそれらを共有または再利用するための安全かつ効率的な方法を見つけることです。私は、これらが毎回書式文字列から作成するのは高価だと想像することができます。これらは、JSFアプリケーションのデータテーブルの中で使用されます(エントリ数が多い可能性があります)。これらのDateFormatオブジェクトをすべて作成することの費用は簡単ではないかもしれません。 –

関連する問題