[フレームワーク]IOC

J2EEを使ってアプリケーション開発を行う場合、EJBを使用するが、EJB2.0には不便な点があります。
1つは、トランザクション制御が宣言的である事です。もう1つは、EJBの開発及び配置が複雑な事です。

EJBは、トランザクション制御が宣言的であるため、ある特定の処理を行うEJBを開発して、その処理を異なるトランザクション境界で呼び出そうとする場合、同じEJBを違うトランザクション宣言で2つ配置する必要があります。
呼び出される側がトランザクションを宣言するのではなく、呼び出す側がトランザクションを宣言したくなるのです。
これを実現するのがIOCです。IOCの言葉の由来は、Inversion Of Controlつまり"制御の反転"です。

EJBには、分散環境での透過的な呼び出しや、JMSとの組み合わせによる非同期呼び出し、トランザクション制御、流量制御などアプリケーションにとって便利な機能が色々とあります。
しかしながら、その利点を享受するために、複雑なEJB開発及び配置方法を理解する必要があります。
これらの利点を享受しつつ、アプリケーションを簡単に作りたいのです。そのためには、EJBをアプリケーションが直接実装せず、フレームワークとして組み上げられたEJBをアプリケーションが利用すればよいのです。

IOCは、EJBをフレームワークとして配置し、その先で業務フローを動かす事で、アプリケーションはEJBを意識せずに、EJBの機能を利用できるフレームワークです。
IOCでは、4つのEJBを配置します。
まず、呼び出し口として、Facade Stateless Session BeanとFacade Message Driven Beanです。それぞれ、同期呼び出しと非同期呼び出しの呼び出し口となります。
次が、Unit of Work Stateless Session Beanです。このEJBは、トランザクション宣言をRequired Newに宣言する事でトランザクション境界となります。
最後が、Command Stateless Session Beanです。このEJBは、末端で業務フローを呼び出します。

これらのEJBをどのような順番で呼び出し、業務フローを実行するのかを、FacadeValueUnitOfWorkCommandを組み合わせる事で、制御してトランザクション境界を呼び出し側が決定します。
また、IOC自体は、EJBでありEJBの呼び出しが煩雑であるため、その呼び出しを隠ぺいするFacadeCallerを提供します。

IOCの機能性は、Nimbusの開発過程において業務フローの機能として取り込まれ、Nimbus2では機能自体が廃止されているため、非推奨です。

関連するパッケージは、以下です。

アプリケーション向けインタフェース FacadeCaller

アプリケーション向けインタフェースFacadeCallerを使った簡単なアプリケーションのサンプルを示します。

  1. import java.util.*;
  2. import jp.ossc.nimbus.core.ServiceManagerFactory;
  3. import jp.ossc.nimbus.ioc.FacadeValueAccess;
  4. import jp.ossc.nimbus.ioc.FacadeValue;
  5. import jp.ossc.nimbus.ioc.UnitOfWork;
  6. import jp.ossc.nimbus.ioc.Command;
  7. import jp.ossc.nimbus.service.ioccall.FacadeCaller;
  8. // サービスを取得する
  9. FacadeCaller caller = (FacadeCaller)ServiceManagerFactory.getServiceObject("FacadeCaller");
  10. // トランザクション境界となるUnitOfWorkを生成する
  11. UnitOfWork uow = FacadeValueAccess.createUnitOfWork();
  12. // コマンドを生成する
  13. Command command1 = FacadeValueAccess.createCommand("Flow1", null);
  14. // コマンドをUnitOfWorkに追加する
  15. uow.addCommand(command1);
  16. // コマンドを生成する
  17. Command command2 = FacadeValueAccess.createCommand("Flow2", null);
  18. // コマンドをUnitOfWorkに追加する
  19. uow.addCommand(command2);
  20. // コマンドを生成する
  21. Command command3 = FacadeValueAccess.createCommand("Flow3", null);
  22. // FacadeValueを生成する
  23. FacadeValue fv = FacadeValueAccess.createCommandsValue();
  24. // UnitOfWorkをFacadeValueに追加する
  25. fv.addUnitOfWork(uow);
  26. // コマンドをUnitOfWorkに追加する
  27. fv.addCommand(command3);
  28. // 同期実行する
  29. FacadeValue result = caller.syncFacadeCall(fv);
  30. // 実行結果が成功しているか確認する
  31. if(result.getStatus() != CommandBase.C_STATUS_COMPLETE){
  32. System.out.println("実行失敗:" + result.getStatus());
  33. // 例外が発生しているか確認する
  34. if(result.getExceptionCount() != 0){
  35. Throwable[] exceptions = result.getExceptions();
  36. for(int i = 0; i < exceptions.length; i++){
  37. exceptions[i].printStackTrace();
  38. }
  39. }
  40. }

実装サービスの一覧は以下のとおりです。

実装サービス実装概要
jp.ossc.nimbus.service.ioccall.DefaultFacadeCallServiceデフォルト実装

サンプルは、以下。