23

シリアル化に関連する問題はまだ発生していません。しかし、PMDとFindbugsは、セリアゼーションに関する多くの潜在的な問題を検出します。典型的なケースは、シリアライズ不可能として検出されている注入されたロガーです。しかし、もっとたくさんあります-EntityManagerそしていくつかのCDIBean。

シリアル化を正しく処理する方法に関するベストプラクティスは見つかりませんでした。

  • デシリアライズによって注入され@Inject、再注入されるフィールドはありますか?@PersistenceContext
  • それらはとしてマークする必要がありtransientますか?
  • または、コードチェックを無視/オフにする必要がありますか?
  • PMDがアドバイスするように、これらすべてのフィールドへのアクセサーを本当に提供する必要がありますか?
4

3 に答える 3

27

これは古い質問だと思いますが、提供された唯一の答えは間違っていると思います。

@Injectと@PersistenceContextによって注入されたフィールドは、逆シリアル化時に再注入されますか?

いいえ彼らはしません。私は、クラスター環境でJBossを使用してこれを個人的に経験しました。Beanがパッシベーションに対応している場合、コンテナはシリアル化可能なプロキシを注入する必要があります。そのプロキシはシリアル化および逆シリアル化されます。デシリアライズされると、適切なインジェクションを見つけて再配線します。ただし、フィールドを一時的とマークすると、プロキシはシリアル化されず、注入されたリソースにアクセスしたときにNPEが表示されます。

プロキシがシリアル化されるため、注入されたリソースまたはBeanはシリアル化可能である必要はないことに注意してください。唯一の例外は、シリアル化可能である必要がある@DependentスコープのBeanまたはインジェクショントランジェントです。これは、この場合プロキシが使用されていないためです。

それらは一時的なものとしてマークする必要がありますか?

いいえ、上記を参照してください。

または、コードチェックを無視/オフにする必要がありますか?

これはあなた次第ですが、私がすることです。

PMDがアドバイスするように、これらすべてのフィールドへのアクセサーを本当に提供する必要がありますか?

いいえ、しません。私たちのプロジェクトでは、CDIを使用していることがわかっている場合は、このチェックを無効にします。

于 2013-11-19T17:57:09.270 に答える
8

この回答では、EJB 3.2( JSR 345)、JPA 2.1(JSR 338)、およびCDI 1.2(JSR 346 )のシリアル化/パッシベーションのセマンティクスについて詳しく説明します。注目に値するのは、Java EE 7アンブレラ仕様(JSR 342)、Managed Beans 1.0仕様(JSR 316)、およびCommons Annotations仕様1.2(JSR 250)には、シリアル化に関して私たちが関心を持っていることは何もありません。パッシベーション。

また、静的コードアナライザーのトピックにも触れます。

EJB

関連するセクションは、「4.2ステートフルセッションBeanの会話状態」および「4.2.1インスタンスのパッシベーションと会話状態」です。

@Stateless@Singletonインスタンスが不動態化されることはありません。

@Statefulインスタンスは不動態化される場合があります。EJB 3.2以降、クラス開発者はを使用してパッシベーションをオプトアウトできます@Stateful(passivationCapable=false)

EJB仕様では、、、およびコンテナー管理などへの参照はコンテナーによって処理されることが明示的に示さUserTransactionEntityManagerFactoryEntityManagerいます。拡張永続コンテキストを使用する@Statefulインスタンスは、永続コンテキスト内のすべてのエンティティとEntityManager実装がシリアル化可能でない限り、不動態化されません。

アプリケーション管理のEntityManagerは、常に拡張永続コンテキストを使用することに注意してください。また、@ Statefulインスタンスは、拡張永続コンテキストを持つコンテナ管理のEntityManagerを使用できる唯一のタイプのEJBセッションインスタンスです。この永続コンテキストは、単一のJTAトランザクションではなく、@Statefulインスタンスのライフサイクルにバインドされます。

EJB仕様は、拡張永続コンテキストを持つコンテナ管理のEntityManagerに何が起こるかを明示的に扱っていません。私の理解はこれです:拡張された永続コンテキストがある場合、この男は以前に定義されたルールに従ってシリアル化可能であるかどうかと見なされる必要があり、そうである場合、パッシベーションが進行します。パッシベーションが進行する場合、@ Statefulクラスの開発者は、アプリケーション管理のエンティティマネージャーへの参照のみを考慮する必要があります。

EJB仕様では、開発者が行う必要のある仮定を説明する以外に、一時フィールドに何が起こるかを指定していません。

セクション4.2.1は言う:

Beanプロバイダーは、一時フィールドのコンテンツがPrePassivate通知とPostActivate通知の間で失われる可能性があることを想定する必要があります。

[...]

コンテナは、不動態化されたセッションインスタンスの状態を格納するためにJavaプログラミング言語のシリアル化プロトコルを使用する必要はありませんが、同等の結果を達成する必要があります。唯一の例外は、アクティブ化中に一時フィールドの値をリセットするためにコンテナが必要ないことです。一般に、セッションBeanのフィールドを一時的なものとして宣言することはお勧めしません。

コンテナにJavaのシリアル化プロトコルと「同等の結果を達成する」ことを要求すると同時に、一時的なフィールドで何が起こるかについて完全に特定されないままにすることは、正直なところ、非常に悲しいことです。持ち帰りの教訓は、一時的なものとしてマークするものは何もないということです。コンテナが処理できないフィールドの場合は、を使用@PrePassivateして書き込みnull@PostActivate復元を行います。

JPA

「パッシベーション」という言葉は、JPA仕様では使用されていません。また、 JPAは、、、、などEntityManagerFactoryの型のシリアル化セマンティクスを定義していません。私たちに関連する仕様の唯一の文はこれです(セクション「6.9クエリの実行」):EntityManagerQueryParameter

CriteriaQuery、CriteriaUpdate、およびCriteriaDeleteオブジェクトはシリアル化可能である必要があります。

CDI

セクション「6.6.4。不動態化スコープ」は、不動態化スコープを明示的に注釈が付けられたスコープとして定義します@NormalScope(passivating=true)。このプロパティのデフォルトはfalseです。

1つの意味は@Dependent、疑似スコープである-はパッシベーション対応のスコープではないということです。javax.faces.view.ViewScopedまた、インターネットの大部分が何らかの理由で信じているように見えるパッシベーション対応のスコープではないことも注目に値します。たとえば、「Java 9 Recipes:AProblem-SolutionApproach」という本のセクション「17-2.JSFアプリケーションの開発」。

パッシベーション対応スコープでは、「スコープを使用してパッシベーション対応」と宣言されたクラスのインスタンスが必要です(セクション「6.6.4。パッシベーションスコープ」)。セクション「6.6.1。パッシベーション対応Bean」では、このようなオブジェクトインスタンスを単にセカンダリストレージに転送可能なものとして定義しています。特別なクラス注釈またはインターフェースは、明示的な要件ではありません。

EJBのインスタンス:s @Statelessおよび@Singletonは、「パッシベーション対応Bean」ではありません。@Statefulは可能性があります(ステートフルは、CDIにライフサイクルを管理させることが理にかなっている唯一のEJBセッションタイプです。つまり、CDIスコープを@Statelessまたは@Singletonに配置しないでください)。他の「マネージドBean」は、それらとそのインターセプターおよびデコレーターがすべてシリアル化可能である場合にのみ「パッシベーション対応Bean」になります。

「パッシベーション対応Bean」として定義されていないということは、ステートレス、シングルトン、EntityManagerFactory、EntityManager、Event、BeanManagerなどを、作成したパッシベーション対応インスタンス内の依存関係として使用できないことを意味するわけではありません。これらは、代わりに「パッシベーション対応の依存関係」として定義されます(「6.6.3。パッシベーション対応の依存関係」および「3.8。追加の組み込みBean」を参照)。

CDIは、パッシベーション対応プロキシを使用して、これらの依存関係をパッシベーション可能にします(セクション「5.4。クライアントプロキシ」およびセクション「7.3.6。リソースのライフサイクル」の最後の箇条書き項目を参照)。EntityManagerFactoryやEntityManagerなどのJavaEEリソースをパッシベーション対応にするには、CDIプロデューサーフィールドとして宣言する必要があり(セクション「3.7.1。リソースの宣言」)、@Dependent以外のスコープをサポートしないことに注意してください。 (セクション「3.7。リソース」を参照)そして、@Injectを使用してクライアント側で検索する必要があります。

他の@Dependentインスタンスは、通常のスコープで宣言されておらず、CDI「クライアントプロキシ」の前に置く必要はありませんが、インスタンスがセカンダリストレージに転送可能、つまりシリアル化可能である場合、パッシベーション対応の依存関係として使用することもできます。この男はクライアントと一緒にシリアル化されます(セクション「5.4。クライアントプロキシ」の最後の箇条書き項目を参照)。

完全に明確にし、いくつかの例を提供すること。@Statelessインスタンス、CDIによって生成されたEntityManagerへの参照、およびシリアル化可能な@Dependentインスタンスはすべて、パッシベーション対応スコープで注釈が付けられたクラス内のインスタンスフィールドとして使用できます。

静的コードアナライザー

静的コードアナライザーは愚かです。上級開発者にとって、彼らは補佐官であるよりも懸念の原因であると思います。シリアル化/パッシベーションの問題が疑われる場合にこれらのアナライザーによって生成される偽のフラグは、インスタンスが「本当にパッシベーションに対応しており、さらに、その依存関係がパッシベーションに対応している」か、または「 javax.enterprise.inject.spi.DeploymentExceptionのサブクラス」(セクション「6.6.5。パッシベーション対応のBeanと依存関係の検証」および「2.9。コンテナによって自動的に検出された問題」)。

最後に、他の人が指摘しているように、繰り返す価値があります。おそらく、フィールドをとしてマークするべきではありませんtransient

于 2017-08-14T19:30:47.320 に答える
1

PMDとFindBugsはインターフェースをチェックしているだけで、コードが実行される環境に関する情報もありません。ツールを静めるために、それらを一時的なものとしてマークすることができますが、一時的なキーワードに関係なく、逆シリアル化と最初の使用時にすべてが適切に再注入されます。

于 2012-12-05T06:50:21.797 に答える