web-dev-qa-db-ja.com

EJB 3.1およびCDIを使用する場所

Java EEベースの製品を作成しています。この製品では、 GlassFish 3とEJB 3.1を使用しています。

私のアプリケーションには、スケジューラー セッションBean があり、Webサービスを使用しています。最近、 Apache TomEE について知りました。これは Contexts and Dependency Injection(CDI) をサポートしています。 GlassFishコンテナはCDIもサポートしています。

CDIがまだ提供していない機能を必要としないセッションBeanを置き換えることはできますか?もしそうなら、私が得ることができる利点は何ですか?

114
Dhrumil Shah

はい、CDIとEJBの両方を自由に組み合わせて、素晴らしい結果を得ることができます。 @WebService@Scheduleを使用しているように聞こえますが、これらはEJBをミックスに追加する良い理由です。

そこには多くの混乱がありますので、EJBとCDIが互いに関連する一般的な情報を以下に示します。

EJB> = CDI

EJB are CDI Beanであるため、CDIのすべての利点があることに注意してください。その逆は(まだ)真実ではありません。そのため、「EJB vs CDI」という考え方は、「EJB + CDI vs CDI」という奇妙な方程式に実際に変換されるため、絶対に考えないでください。

Java EEの将来のバージョンでは、それらを調整し続けます。調整手段とは、先頭に@Stateful@Stateless、または@Singletonアノテーションがなくても、既にできることを実行できるようにすることです。 。

実装用語のEJBおよびCDI

最終的に、EJBとCDIは、プロキシコンポーネントであるという同じ基本設計を共有します。 EJBまたはCDI Beanへの参照を取得するとき、それは実際のBeanではありません。むしろ、与えられたオブジェクトは偽物(プロキシ)です。この偽オブジェクトのメソッドを呼び出すと、呼び出しはコンテナーに送られ、コンテナーはインターセプターやデコレーターなどを介して呼び出しを送信し、トランザクションまたはセキュリティチェックを処理します。すべてが完了すると、呼び出しは最終的に実際のオブジェクトに行き、結果はプロキシを介して呼び出し元に返されます。

違いは、呼び出されるオブジェクトがどのように解決されるかだけです。 「解決」とは、コンテナが実際のインスタンスを呼び出して呼び出す場所と方法を意味するだけです。

CDIでは、コンテナは基本的に特定の期間(リクエスト@RequestScoped、HTTPセッション@SessionScopedごと、アプリケーション@ApplicationScopedごと、JSFカンバセーション@ConversationScopedごと、またはカスタムスコープの実装ごとに)存在するハッシュマップとなる「スコープ」を探します。 。

EJBでは、Beanのタイプが@Statefulの場合、コンテナーはハッシュマップも調べます。 @Stateful Beanは、上記のスコープアノテーションのいずれかを使用して、スコープ内の他のすべてのBeanとともに存続および終了させることもできます。 EJBでは、@Statefulは基本的に「任意のスコープ」Beanです。 @Statelessは基本的にインスタンスプールです。1回の呼び出しの間、プールからインスタンスを取得します。 @Singletonは基本的に@ApplicationScopedです

したがって、基本的なレベルでは、「EJB」Beanでできることはすべて、「CDI」Beanでできるはずです。カバーの下では、それらを区別するのは非常に困難です。インスタンスの解決方法を除いて、すべての配管は同じです。

現在、このプロキシを行うときにコンテナが提供するサービスの点では同じではありませんが、私が言うようにJava EE仕様レベルで作業しています。

パフォーマンスノート

あなたが持っているかもしれない「軽い」または「重い」精神的なイメージを無視してください。それがすべてのマーケティングです。ほとんどの部分が同じ内部設計になっています。 CDIインスタンスの解決は、もう少し動的でコンテキストに依存するため、おそらくもう少し複雑です。比較すると、EJBインスタンスの解決はかなり静的で、愚かで単純です。

TomEEの実装の観点から言えますが、EJBの呼び出しとCDI Beanの呼び出しのパフォーマンスの差はほぼゼロです。

デフォルトはPOJO、CDI、EJB

もちろん、メリットがない場合はCDIやEJBを使用しないでください。インジェクション、イベント、インターセプター、デコレーター、ライフサイクルトラッキングなどが必要になったら、CDIを投入します。それはほとんどの時間です。

これらの基本を超えて、@Stateful@Stateless、または@Singletonを追加してCDI BeanをEJBにする場合にのみ使用できるオプションがある便利なコンテナサービスがいくつかあります。

以下に、EJBを分類する短いリストを示します。

JAX-WSの使用

JAX-WS @WebServiceを公開しています。私は怠け者。 @WebServiceもEJBである場合は、web.xmlファイルにリストしてサーブレットとしてマップする必要はありません。それは私にとって仕事です。さらに、以下に記載されている他の機能を使用するオプションがあります。だから、私にとっては簡単です。

@Statelessおよび@Singletonでのみ使用可能です。

JAX-RSの使用

@Pathを介したJAX-RSリソースの公開。私はまだ怠け者です。 RESTfulサービスもEJBである場合、再び自動検出が行われ、JAX-RS Applicationサブクラスまたはそのようなものに追加する必要はありません。さらに、以下で説明する優れた機能のいずれかを使用する場合は、@WebServiceとまったく同じBeanを公開できます。

@Statelessおよび@Singletonでのみ使用可能です。

起動ロジック

@Startupを介して起動時にロードします。現在、CDIにはこれに相当するものはありません。どういうわけか、コンテナライフサイクルでAfterStartupイベントのようなものを追加するのを逃しました。これを実行していた場合、それをリッスンする@ApplicationScoped Beanがあれば、それは@Singletonを使用した@Startupと実質的に同じになります。 CDI 1.1のリストに載っています。

@Singletonでのみ使用可能です。

並行して作業する

@Asynchronousメソッド呼び出し。スレッドを開始することは、サーバー側の環境では不可です。スレッドが多すぎると、パフォーマンスが著しく低下します。この注釈により、コンテナのスレッドプールを使用して行うことを並列化できます。これはすごい。

@Stateful@Stateless、および@Singletonで使用できます。

スケジューリング作業

@ScheduleまたはScheduleExpressionは、基本的にはcronまたはQuartz機能です。また、非常に素晴らしい。ほとんどのコンテナは、このためにQuartzを使用しています。ただし、ほとんどの人は、Java EEでの作業のスケジューリングはトランザクションです!データベースを更新してから作業をスケジュールし、その1つが失敗すると、両方が自動的にクリーンアップされます。 EntityManager persist呼び出しが失敗するか、フラッシュに問題があるため、作業のスケジュールを解除する必要はありません。

@Statelessおよび@Singletonでのみ使用可能です。

JTAトランザクションでEntityManagerを使用する

もちろん、トランザクションに関する上記の注意事項では、JTA管理対象EntityManagerを使用する必要があります。これらはプレーンな「CDI」で使用できますが、コンテナ管理のトランザクションがなければ、UserTransactionコミット/ロールバックロジックを本当に単調に複製できます。

CDI、JSF @ManagedBean@WebServlet@WebListener@WebFilterなどを含むすべてのJava EEコンポーネントで利用可能。ただし、@TransactionAttribute注釈は、@Stateful@Stateless@Singletonのみで利用可能です。

JTAを管理するEntityManager

EXTENDED管理対象EntityManagerを使用すると、EntityManagerトランザクション間でJTAを開いたままにし、キャッシュされたデータを失うことはありません。適切な時間と場所に適した機能。責任を持って使用してください:)

@Statefulでのみ使用可能です。

簡単な同期

同期が必要な場合、@Lock(READ)および@Lock(WRITE)アノテーションは非常に優れています。同時アクセス管理を無料で取得できます。すべてのReentrantReadWriteLock配管をスキップします。同じバケットには@AccessTimeoutがあります。これにより、スレッドがBeanインスタンスへのアクセスを取得するまで待機する時間を指定できます。

@Singleton Beanのみで利用可能です。

375
David Blevins

ejb 3.1の機能を実際に使用していない場合、答えは簡単です。しかし、あなたの質問は、あなたがそれらに気づかないで恩恵を受けているEJB 3.1の概念があると疑うことを示していると思います。一例として、コンテナはslsbのプールを使用する準備ができているため、jmsおよびデータベース接続をリクエストの一部として挿入する必要はありません。

2
Aksel Willgert