EJB 3.1とCDIはどこで使用しますか?


120

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

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

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

回答:


408

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

そこには多くの混乱があるので、EJBとCDIがそれぞれに関連しているため、EJBとCDIに関する一般的な情報をいくつか示します。

EJB> = CDI

EJB CDI Beanであるため、CDIのすべての利点があることに注意してください。逆は(まだ)真実ではありません。そのため、「EJB対CDI」を考える習慣をつけないでください。そのロジックは、「EJB + CDI対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豆はまた、スコープ内の他のすべての豆と一緒に暮らすと死なせる上記範囲の注釈のいずれかを使用することができます。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を投入します。それはほとんどの時間です。

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

EJBを分割するときの短いリストを次に示します。

JAX-WSの使用

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

利用可能@Stateless@Singletonのみ。

JAX-RSの使用

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

利用可能@Stateless@Singletonのみ。

起動ロジック

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

@Singletonのみご利用いただけます。

並行して作業する

@Asynchronousメソッド呼び出し。スレッドを開始することは、どのサーバー側環境でも禁止事項です。スレッドが多すぎると、パフォーマンスが大幅に低下します。このアノテーションにより、コンテナーのスレッドプールを使用して行う処理を並列化できます。これは素晴らしいです。

利用可能な@Stateful@Stateless@Singleton

スケジュール作業

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

利用可能@Stateless@Singletonのみ。

JTAトランザクションでのEntityManagerの使用

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

CDI、JSFなど、すべてのJava EEコンポーネントに利用可能な@ManagedBean@WebServlet@WebListener@WebFilter、など@TransactionAttributeのアノテーションは、しかし、に利用できる@Stateful@Stateless@Singletonだけ。

JTAを管理し続ける EntityManager

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

@Statefulのみご利用いただけます。

簡単な同期

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

@SingletonBeanでのみ使用できます。


32
グッド天国デビッド:)私はあなたがそれをカバーしたと思います。
LightGuard、2012年

7
この回答をありがとうございます。あなたは私の頭の中の詰まりを取り除き、たくさんの点をつなぎました。
2014

7
これは、私が今まで読んだそのトピックに関する断然最高の説明です。また、実際の使用におけるEJBのほぼすべての重要な側面もカバーしています。すごい仕事!!
nanoquack 14

3
非常に理解可能であり、厳格な法的条件でAdamが間違っているわけではありませんが、区別は根拠のないものです。仕様では、EJBインスタンスはコンテキストに依存しないと述べていますが、後でEJBへの参照(プロキシ)はコンテキストに依存すると述べています。ステートフルBeanのライフサイクルは参照(プロキシ)によって完全に制御されるため、CDIコンテナがその参照(プロキシ)を制御している場合、計算は同じです-ステートフルEJBは事実上コンテキストに依存します。
David Blevins、2014年

3
TESLAでの昼休みにこれを書きましたか?
エジソン

2

ejb 3.1の機能をまったく使用していない場合、答えは簡単です。しかし、あなたの質問があなたがそれらに気付かないであなたが利益を得ているejb 3.1の概念があるのではないかと疑っていることを推測すると思います。1つの例として、コンテナーがslsbのプールを使用可能な状態に保つことができるため、jmsとデータベース接続を要求の一部として挿入する必要がない場合があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.