22

ローカライズされた文字列を簡単に取得するために、任意のクラスに java.util.ResourceBundle を挿入できるプロデューサーを作成したいと考えています。私の ResourceBundle-Producer は次のようになります。

public class ResourceBundleProducer {
  @Inject       
  public Locale locale;

  @Inject       
  public FacesContext facesContext;

  @Produces
  public ResourceBundle getResourceBundle() {
    return ResourceBundle.getBundle("/messages", locale )
  }
}

Locale と FacesContext のインジェクションが機能します (Seam 3 Alpha Source から対応するプロデューサーを取得しました)。残念ながら、ResourceBundle は Serializable ではないため、この方法で生成することはできません。ResourceBundle を使用する Bean を呼び出す JSF ページにアクセスしようとすると、Weld から次のエラーが発生します。

Caused by: org.jboss.weld.IllegalProductException: WELD-000054 Producers cannot produce non-serializable instances for injection into non-transient fields of passivating beans\\n\\nProducer\: org.jboss.weld.bean-/D:/Program Files (x86)/GlassFish-Tools-Bundle-For-Eclipse-1.2/glassfishv3/glassfish/domains/teachernews/applications/teachernews/-ProducerMethod-services.producers.ResourceBundleProducer.getResourceBundle()\\nInjection Point\: field web.PersonHome.bundle

ResourceBundleResolver を機能させる方法はありますか? または、同様の機能を実現する他のメカニズムはありますか? 前もって感謝します!

編集:

わかりました、ほとんど獲得できなかったポイントの一部を使用します ;) この問題の適切な回避策も受け入れます!

Producer の作成が機能しない別の例があります: FlashProducer です。Flash はシリアル化できないため、FacesContext-Flash も生成できません。

4

2 に答える 2

27

まず、 ResourceBundleは Serializable ではありませんここを参照してください。そして、メッセージは明確です

パッシベーション Bean の非一時的なフィールドに注入するためのシリアル化不可能なインスタンスを生成することはできません

豆のパッシベーション??? web.PersonH ​​omeはステートフル セッション Bean または @ConversationScoped Bean のいずれかだと思います。私は正しいですか?その場合は、バンドル プロパティを一時的なものとしてマークする必要があります

private transient @Inject ResourceBundle bundle;
于 2010-07-17T06:55:44.457 に答える
5

アーサーの受け入れられた回答のコメントスレッドに従って。このブログとこのブログをフォローして、パッシベーション/アクティベーションの実験を行いました。実験は、アクティブ化すると一時的なプロパティが NULL になるという MrD のコメントを証明しました。したがって、パッシベーション対応 Bean (つまり、sessionscoped、conversationscoped、およびステートフル セッション Bean) のシリアル化できないメンバー プロパティを処理するには、次の解決策をお勧めします。

private ResourceBundle bundle;

@PostConstruct
@PostActivate
public void getResourceBundle() {
    bundle = ResourceBundle.getBundle("/messages", locale );
}

このソリューションでは、シリアル化できないプロパティ メンバーが READY 状態になるたびに再初期化されるようにします。

取り組むべき最終的な問題

対処すべき最後の問題は、slf4j 1.5.3 より前ではシリアル化できない SLF4j ロガーのインジェクションです

SLF4J バージョン 1.5.3 の時点で、ロガー インスタンスはシリアライゼーションに耐えます。したがって、ロガーがインスタンス変数として宣言されている場合でも、ホスト クラスのシリアル化に特別なアクションは必要ありません。

したがって、slf4j 依存関係が 1.5.3 以降である限り、次のように SLF4j ロガーを安全に注入できます。

@Produces
@LogbackLogger
public Logger produceLogger(InjectionPoint injectionPoint){
    return LoggerFactory.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}

修飾子を宣言したと仮定します。

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface LogbackLogger {
}

次に、パッシベーション可能な Bean で、次のように注入します。

@Inject
@LogbackLogger
private Logger logger;
于 2014-02-04T20:54:28.300 に答える