| この記事の要点 |
|
EJB とは
EJB (Enterprise JavaBeans) は、Java EE(現 Jakarta EE)におけるサーバサイドの再利用可能コンポーネント仕様です。WebLogic / WildFly / GlassFish / Open Liberty などのEJB コンテナにデプロイされ、トランザクション・セキュリティ・並行制御・プーリングといった非機能要件をコンテナが面倒を見ます。
歴史と現状
| 世代 | 年 | 特徴 |
|---|---|---|
| EJB 1.x / 2.x | 1999-2003 | 重厚な XML 記述 / Home/Remote 二重インターフェース / 開発生産性悪い → 不人気 |
| EJB 3.0 | 2006 | アノテーション化、POJO ベース。Entity Bean は JPA として分離 |
| EJB 3.1 | 2009 | Singleton SessionBean、no-interface view、組み込み EJB Container |
| EJB 3.2 | 2013 | Java EE 7、徐々に CDI へシフト |
| Jakarta EE 8/9/10 | 2019- | 名前空間が javax.ejb → jakarta.ejb、EJB Lite で軽量化 |
SessionBean の種類
Stateless Session Bean
状態を持たない・最もよく使われる業務ロジック実装。コンテナがプールでインスタンスを使い回します。
import jakarta.ejb.Stateless;
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
@Stateless
public class OrderService {
@PersistenceContext
private EntityManager em;
public Order createOrder(Long userId, List<Long> productIds) {
// メソッド単位で自動的にトランザクション開始/コミット
Order order = new Order(userId);
for (Long pid : productIds) {
Product p = em.find(Product.class, pid);
order.addItem(p);
}
em.persist(order);
return order;
}
}
// 呼び出し側
@Inject
private OrderService orderService;
orderService.createOrder(userId, productIds);
Stateful Session Bean
クライアントセッション単位で状態を保持する。ショッピングカートのような用途。
import jakarta.ejb.Stateful;
import jakarta.ejb.Remove;
@Stateful
public class ShoppingCart {
private final List<Item> items = new ArrayList<>();
public void addItem(Item item) {
items.add(item);
}
public List<Item> getItems() {
return List.copyOf(items);
}
@Remove // 呼ばれるとインスタンス破棄
public void checkout() {
// ...
}
}
Singleton Session Bean
アプリ全体で1 インスタンス。設定キャッシュなどに。
import jakarta.ejb.Singleton;
import jakarta.ejb.Startup;
import jakarta.annotation.PostConstruct;
@Singleton
@Startup // 起動時に初期化
public class ConfigCache {
private Map<String, String> cache = new ConcurrentHashMap<>();
@PostConstruct
public void load() {
// DB から設定読み込み
}
public String get(String key) {
return cache.get(key);
}
}
Message-Driven Bean (MDB)
JMS キュー/トピックを受信して非同期処理。
import jakarta.ejb.MessageDriven;
import jakarta.ejb.ActivationConfigProperty;
import jakarta.jms.Message;
import jakarta.jms.MessageListener;
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "jakarta.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination",
propertyValue = "java:/queue/orders")
})
public class OrderProcessor implements MessageListener {
@Override
public void onMessage(Message msg) {
// メッセージ処理
}
}
トランザクション制御
EJB はメソッド単位の宣言的トランザクションを持つのが最大の特徴:
import jakarta.ejb.TransactionAttribute;
import jakarta.ejb.TransactionAttributeType;
@Stateless
public class PaymentService {
// デフォルトで REQUIRED(既存 TX に参加、無ければ新規)
public void pay(Order o) { ... }
// 必ず新トランザクションで(既存 TX を中断)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void logAuditTrail(Order o) { ... }
// トランザクション無しで実行
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public List<Order> readReport() { ... }
}
EJB と JPA Entity
かつての EJB 1.x/2.x では Entity Bean も EJB 仕様の一部でしたが、EJB 3.0 以降は JPA (Java Persistence API) として完全分離。Entity は単なる POJO + アノテーションです。
@Entity
@Table(name = "orders")
public class Order {
@Id @GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> items;
// getter/setter
}
EJB vs CDI
| EJB | CDI | |
|---|---|---|
| 用途 | 業務ロジック・TX・分散 | DI とスコープ管理 |
| トランザクション | 宣言的 (デフォルト REQUIRED) | CDI 単体は無し、@Transactional で対応 |
| プーリング | あり (Stateless) | 無し(Scope に依存) |
| 分散呼び出し | RMI/IIOP, EJB Remote 可 | 不可 |
| 非同期 | @Asynchronous | CDI Async Events (4.0+) |
| セキュリティ | @RolesAllowed | Jakarta Security と統合 |
| 軽量性 | 重め | 軽い |
現代の Jakarta EE はCDI を主軸に、必要に応じて EJB の機能を借りる構成が主流。
Spring Boot との比較
| 機能 | EJB | Spring Boot |
|---|---|---|
| DI | @EJB / @Inject | @Autowired |
| 業務ロジック | @Stateless | @Service |
| トランザクション | 暗黙の REQUIRED | @Transactional 明示 |
| 非同期 | @Asynchronous | @Async + ThreadPool |
| メッセージング | MDB | @KafkaListener / @RabbitListener |
| 運用 | EJB コンテナ必須 (WildFly等) | 組込 Tomcat / Jetty で単独 JAR |
| 学習コスト | 高い | 低〜中 |
現代における EJB の立ち位置
- 新規プロジェクトの多くは Spring Boot または Micronaut / Quarkus
- Jakarta EE 新規案件でも EJB Lite(Stateless / トランザクション のみ)に絞る
- WebLogic / WAS など商用 EJB コンテナ運用中の既存システムでは現役
- 軽量化トレンド: マイクロサービス時代、起動の重い EJB は敬遠される傾向
- 金融・大企業の分散トランザクション (JTA + XA) で残る価値あり
FAQ
Q: EJB はもう使わなくていい?
A: 新規 Greenfield なら Spring Boot で十分です。ただし既存 EJB システムの保守、JTA 分散トランザクション要件、商用 AP サーバ標準化された企業では現役。
Q: @Stateless と Spring の @Service の違いは?
A: @Service は単なる DI 対象。@Stateless はプール管理 + 暗黙トランザクション + リモート呼び出し可。Spring で同等は @Service @Transactional。
Q: Stateful Session Bean は使うべき?
A: スケーラビリティ上、分散環境では扱いにくい(クライアント-Bean アフィニティ管理)。マイクロサービスでは Redis セッションや JWT を推奨。
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- プロジェクトをTomcatプロジェクトとして認識させる方法 2026-10-07 22:32:50
- MySQLの1366 Incorrect string value|Laravelの文字コード・絵文字エラー 2026-10-07 21:54:03
- curlの証明書ホスト名不一致|旧エラー51・現行60の確認と対処 2026-10-07 21:54:03
- LaravelのMassAssignmentException|fillableの原因と安全な対処 2026-10-07 21:54:03
- Eclipse で Tomcat の起動ログがコンソールに出ない時の確認手順 2026-10-07 21:54:02
- MySQLにおける中央値(Median)の導き方(バージョン8未満) 2026-10-07 13:49:45
- getInputForward 2026-10-07 13:41:15
- JSONから配列に変換 2026-10-07 13:41:15
- ビューから値をモデルに格納しコントローラーで受け取る方法 2026-10-07 13:23:41
- Laravelのテーブル作成と定義変更|マイグレーション・up/down・注意点 2026-10-07 13:23:41
- NumPy 配列に要素を追加する方法 (append / concatenate) 2026-10-07 13:23:41
- MariaDB・MySQLで現在日時を取得する方法|NOW・タイムゾーン・保存型 2026-10-07 13:13:36
- 【django】テンプレートで定数を使用する方法 2026-10-07 13:10:15
- Spring BootにおけるApplication.propertiesの環境依存設定の分割方法 2026-10-07 12:09:35
- Not supported for DML operations【Springエラー】 2026-10-07 11:09:38