インスタンス変数としてサーブレットにEJBを注入するのは安全ですか?
-
03-07-2019 - |
質問
Web層では、複数のリクエストを処理する特定のサーブレットのインスタンスが1つだけ存在する可能性があることを知っています。これにより、インスタンス変数でスレッドの問題が発生する可能性があります。
私の質問は、@ EJBアノテーションを使用してEJBをインスタンス変数としてサーブレットに注入しても安全ですか?
EJBの同じインスタンスが同時に複数のリクエストを処理するという仮定の下では、私の最初の本能はノーになります。これは、他の多くのプログラマの本能でもあるように思われます。サーブレットに注入しない
しかし、間違った結論に飛びついた。明らかに、サーブレットに注入されるのはプロキシです。実際には、コンテナーは実際には各リクエストを異なるインスタンスで処理し、スレッドの安全性を維持していますか?このフォーラムが示唆するように:サーブレットに注入する
多くの相反する意見があるようです。正しいもの???
解決
参照「サーブレットに注入しないでください」」 ejbsまたは@ejbアノテーションについては何も言及していません。 PersistenceContextなどのスレッドセーフではないオブジェクトについて説明します。
EJB仕様ごとに、サーブレットを含むさまざまなリモートクライアントからejbにアクセスできます(EJB 3.0仕様(JSR-220)-セクション3.1)。 @EJBアノテーションを使用したejbの注入は、JNDI名前空間でejbオブジェクトをルックアップする代わりに、依存性注入(セクション3.4.1)を介してEJBインターフェースを取得する方法です。そのため、取得したEJBに関して@EJBアノテーションについて特別なことはありません。
したがって、EJB 3.0仕様に基づいて、@ EJBアノテーションを使用してサーブレットからejbsを取得するのが標準的な方法です。
他のヒント
EJBがステートレスである限り、EJBをサーブレットインスタンス変数としてサーブレットに挿入しても安全です。サーブレットにステートフルBeanを決して挿入しないでください。
ステートフル値を保持するインスタンス変数(永続コンテキストなど)を保持しないという点で、EJBをステートレスに実装する必要があります。永続コンテキストを使用する必要がある場合は、EJBのメソッドでそのインスタンスを取得する必要があります。これを行うには、PersistenceContextFactoryをEJBインスタンス変数として使用し、EJBのメソッドでファクトリからエンティティマネージャーのインスタンスを取得します。
PersistenceContextFactoryはスレッドセーフであるため、インスタンス変数に挿入できます。
上記のルールに準拠している限り、サーブレットにステートレスBeanを挿入することはスレッドセーフである必要があります
混合バッグです。
ステートレスセッションBeanが挿入されても安全です。これは、スタブの単一インスタンスが使用されている場合でも、メソッドへのアクセスがコンテナによってシリアル化されるためです。
推論されたデザインの言うことは真実ではないと思います。ステートレスセッションBeanが永続コンテキストを使用するかどうかは関係ありません。一度に1つの呼び出し元のみが単一のBeanインスタンスにアクセスするため、永続コンテキストはスレッドセーフではありませんが、EJBはそのインスタンスへの複数アクセスを防ぎます。すべてのセッションBeanメソッドにsynchronizedキーワードが適用されていると考えてください。
EJBをサーブレットに注入する際の主な問題はパフォーマンスです。単一のスタブインスタンスは、セッションBeanメソッドが実行されるのを待っている間に複数のリクエストがキューに入れられると、競合の主要な領域になります。
簡単な答えは、安全であるとは限らないということです。
この理由は、EJBの仕様には、EJBホームインターフェースがスレッドセーフでなければならないという明示的なものがないためです。仕様では、サーバー側部分の動作のみを概説しています。クライアントスケルトンは実際にはスレッドセーフですが、使用しているライブラリによってそれらがどのように実装されているかを確認する必要があるでしょう。アノテーション部分はサービスロケーターに展開されるだけなので、何も購入しません。