EJBとは何ですか?EnterpriseJavaBeansの進化

Enterprise JavaBeans(EJB)は、Javaプラットフォーム上で大規模な分散ビジネスアプリケーションを開発するための仕様です。EJB1.0は1998年にリリースされました。最新のリリースであるEJB3.2.3がJakartaEEに含まれるように採用され、Jakarta EnterpriseBeansに名前が変更されます。

EJBアーキテクチャ

EJBアーキテクチャは、エンタープライズBean(EJB)、EJBコンテナ、およびJavaアプリケーションサーバーの3つの主要コンポーネントで構成されています。EJBはEJBコンテナ内で実行され、EJBコンテナはJavaアプリケーションサーバー内で実行されます。

EJBには、セッションBeanとメッセージ駆動型Beanの2種類があります。

  • セッションBeanはクライアントによって呼び出され、トランザクションやリソース管理などのエンタープライズ機能をクライアントがプログラムで利用できるようにします。
  • メッセージ駆動型Beanもエンタープライズ機能をカプセル化して提供しますが、非同期でイベント駆動型です。メッセージ駆動型Beanはイベントをリッスンして応答し、クライアントから呼び出すことはできません。

EJBシステムで永続性を提供するために使用されると、エンティティBeanはJava PersistenceAPIに取って代わられました。セッションBeanとメッセージ駆動型Beanの詳細については、読み続けてください。

EJBとJavaBeans

Enterprise JavaBeansは、JavaEEの最初のコンポーネントベースの開発モデルでした。EJBは、コンポーネントベースであるという点でJavaBeansに似ていますが、類似点はここで終わります。

  • A JavaBeanは、特定の規則に複数のオブジェクトと適合をカプセル化するJavaクラスです。JavaBeansは、主にクライアント側の開発に使用されます。
  • エンタープライズBean(EJB)は、特定のサーバ側機能に染み込んJavaクラスです。エンタープライズBeanは、大規模なビジネスアプリケーションやシステムで使用されます。

セッションBean

セッションBeanは、クライアントによって呼び出すことができるビジネス機能のチャンクを表す、エンタープライズBeanの最も一般的なタイプです。この場合のクライアントは、ローカルJVMまたはリモート呼び出しの別のクラスである可能性があります。

EJBコンテナは、Beanの状態によって決定されるセッションBeanのライフサイクルを管理します。

  • ステートレスセッションBeanは、JavaサーブレットAPIのリクエストスコープに似ています。ステートレスセッションBeanには、呼び出し可能な機能のチャンクが含まれていますが、それ以外はステートレスです。
  • ステートフルセッションBeanは1つのクライアントにのみ関連付けられ、そのクライアントの進行中のセッションに接続します。ステートフルセッションBeanは、サーブレットAPIのセッションスコープと同様に機能します。
  • シングルトンBeanは、サーブレットAPIのアプリケーションスコープに似ています。シングルトンセッションBeanは、クライアントごとに1回だけ存在します。

セッションBeanによるスレッドセーフ

ステートフルセッションBeanには、一度に1つのクライアントしかアクセスできないため、このタイプのBeanを使用している場合はスレッドセーフが保証されます。ステートレスセッションBeanとシングルトンBeanはより柔軟性があり、開発者が管理する必要のある同時接続を可能にします。これらのタイプのBeanを使用する場合は、スレッドセーフに責任があります。

メッセージ駆動型Bean

メッセージ駆動型Bean(MDB)は、JMS(Java Message Service)メッセージを介して呼び出されます。JMSは、メッセージ駆動型Beanがコマンドのリスナーとして機能する分散コマンドパターンのように機能します。メッセージがトピックまたはキューに到着すると、そのトピックをリッスンしているメッセージ駆動型Beanが呼び出されます。

メッセージ駆動型Beanは、セッションBeanほど一般的には使用されませんが、強力です。非同期でイベント駆動型であるため、リソースを節約することが重要な長時間実行ジョブに特に役立ちます。

最も単純なアーキテクチャは、EJBアプリケーションとそのコンテナおよびサーバーで構成され、MDBを処理するメッセージサービスと連携します。本番環境では、アーキテクチャにBeanの消費専用の3番目のコンポーネントが含まれている可能性があります。開発では、これらのコンポーネントはすべて同じローカルマシンで実行できます。

図1は、メッセージ駆動型Beanを使用した典型的なイベント駆動型アーキテクチャーを示しています。

マシュータイソン

メッセージ駆動型Beanの操作は、セッションBeanの使用よりも複雑です。イベント駆動型環境では、通常、ActiveMQのようなメッセージブローカーが必要になります。

セッションBeanはより単純であるため、EJBでより一般的に使用されますが、特にマイクロサービスの爆発的な増加に伴い、イベント駆動型アーキテクチャが普及しています。 

EJBアノテーション

エンタープライズBeanの定義と消費は、EJB仕様にアノテーションを導入するEJB 3.0まで、多くの開発者にとってのこだわりでした。アノテーションを使用すると、JavaEEにあるさまざまな機能用にエンタープライズBeanを非常に簡単に構成できます。EJBアノテーションを開始するには、読み続けてください。

@Stateless:ステートレスセッションBeanを定義します

クラスをステートレスセッションBeanとして指定するにjavax.ejb.Statelessは、リスト1に示すようにアノテーションを使用します。

リスト1. @ Statelessアノテーションの例

 import javax.ejb.Stateless; @Stateless public class MyStatelessBean { public String getGreeting() { return "Hello JavaWorld."; } } 

このステートレスBeanには、引数をとらずに文字列を返す単純な署名が含まれています。ただし、単純さに惑わされないでください。このBeanは、他のBean、サービス、またはアプリケーションのデータレイヤーとの対話など、必要なことをすべて実行できます。

@EJB:ステートレスセッションBeanを消費する

セッションBeanを定義したら、それを使用するのはとても簡単です。

リスト2. @ EJBアノテーションの例

 public class MyServlet extends HttpServlet { @EJB MyStatelessBean myEjb; public void doGet(HttpServletRequest request, HttpServletResponse response) { response.getWriter().write("EJB Says " + testStatelessEjb.getGreeting()); } } 

Here, we inject the stateless bean into a servlet, and then it's available for use. Notice how the bean is identified under the @EJB annotation. The "stateless" designation tells us this bean will not track the client. Because it's stateless, we also know this bean is subject to threading if it does any work outside the invoked method.

@Remote: Define a remote EJB interface

In the above examples, I assumed the EJB and EJB client were running in the same JVM. If the enterprise bean and its client are running in separate JVMs, then the EJB must define a @Remote interface. In this case, it's up to you to define and implement the interface, as shown in Listing 3.

Listing 3. @Remote annotation example

 @Remote public interface MyStatelessEjbRemote { String sayHello(String name); } 

The remote interface is sent to the client to invoke. Calls to it will then be fulfilled by the EJB's server-side implementation. The MyStatelessBean example in Listing 4 implements the remote interface.

Listing 4. Implementing a remote interface

 public class MyStatelessBean implements MyStatelessEjbRemote{ ... } 

A remote interface is implemented just like a normal class implementing an interface. As the consumer of a remote EJB, the client application must be able to access the class definition for the remote interface. You can package the class definition for the remote interface as a dependency JAR.

Local vs remote interface

While it's important to know how to implement a remote interface, in practice it's more common to use a local interface. The local interface is used by default and works whenever the EJB is invoked within the same JVM context. Using the remote interface comes into play when the application is distributed across multiple JVMs.

Stateful sessions beans and singleton beans

The process for defining and consuming stateful @Session beans and @Singleton beans is the same as what you've seen for @Stateless beans. Remember the semantics:

  • Multiple session beans can be instantiated and used for the same client.
  • A singleton bean will exist only once for the entire application.

Thread safety and scheduling with singletons

Thread safety is built in when you're working with session beans, but both stateless and singleton beans can be accessed concurrently by multiple clients. Developers are responsible for thread safety when implementing these types of beans.

Singleton beans offer some support for thread safety via the @Lock annotation. You can use the @Lock annotation on singleton bean methods to set read/write privileges for each method. The two options are @Lock(LockType.READ) or @Lock(LockType.WRITE), which is the default.

Another useful feature of singleton beans is the ability to schedule tasks in a simple way, using the @Schedule annotation. Listing 5 shows how to schedule a task daily at noon.

Listing 5. @Schedule annotation example

 @Singleton public class MySchedulerBean { @Schedule(hour = "12") void doIt() { System.out.println("Hello at Noon!"); } } 

CDI vs EJB

CDI, or Context and Dependency Injection is a newer enterprise specification that some developers have proposed could replace EJB.

At a high level, CDI offers a general-purpose component framework, while EJB stands out for its richly featured, individual components. Whereas CDI uses dependency injection to define and reference any software component, EJB components are more formally defined, with each offering a specific set of capabilities out of the box. Both specs are planned for future development as part of Jakarta EE, where the question of whether CDI should replace EJB will eventually be resolved.

Conclusion

Enterprise JavaBeansは、エンタープライズJavaアプリケーションでビジネスロジックをカプセル化して再利用する簡単な方法を提供する最初の仕様でした。今日のEJBは、昔ながらの巨大なものとはほど遠い、無駄のないアノテーションベースのフレームワークであり、箱から出してすぐにさまざまなエンタープライズ機能にアクセスできます。次回、分散型でスケーラブルなビジネスアプリケーションを迅速に立ち上げるように求められたときは、EJBを検討してください。びっくりするかもしれません。

このストーリー「EJBとは?エンタープライズJavaBeansの進化」は、もともとJavaWorldによって公開されました。