トランザクション
トランザクションは、並列環境におけるデータの完全性を保証する役割を担うという意味で、エンタープライズ開発の重要な要素と位置づけられます。おおざっぱに言えば、トランザクションとは、複数の操作がすべて完了するか、それとも一切完了していないか、そのどちらかであることを保証するものです。トランザクションの詳細については、筆者の以前の記事「Using Annotations with Aspects in Pre-Java 5 Versions」または関連記事を参照してください。
リソース注入やセキュリティのアノテーションと異なり、トランザクションのアノテーションはEJB 3.0固有のもので、JSR 250の共通アノテーションでは規定されていません。EJB 3.0では、トランザクションに関連する2つのアノテーションを規定しています。1つはTransactionManagement
で、もう1つはTransactionAttribute
です。TransactionManager
アノテーションでは、トランザクションをコンテナ管理とするかBean管理とするかを指定します。EJB 3でこのアノテーションを省略した場合は、コンテナ管理のトランザクションと仮定されます。TransactionAttribute
アノテーションは、メソッドのトランザクション伝播レベルを指定します。有効な値はmandatory
、required
、requires new
、supports
、not supported
、never
で、これらは現在のトランザクションが必要かどうか、新しいトランザクションを開始するかどうかなどを指定します。
予約操作は2ステップ(往路と復路の予約)で行われるため、この操作の完全性を保証するためにトランザクションでラップします。EJB 3.0のトランザクションアノテーションを使うと、これは次のようになります。
public class TravelAgencyServiceImpl implements ITravelAgencyService { @Resource(name = "flightDAO") public IFlightDAO flightDAO; @RolesAllowed("user") @TransactionAttribute(TransactionAttributeType.REQUIRED) public void bookTrip(long outboundFlightID, long returnFlightID, int seats) throws InsufficientSeatsException { reserveSeats(outboundFlightID, seats); reserveSeats(returnFlightID, seats); } }
次に簡単なアスペクトを適用します。これでトランザクションの境界が自動的に決定されます。
@Aspect public class TransactionAspect { @Pointcut("execution(@javax.ejb.TransactionAttribute * *.*(..))") public void transactionalMethods() {} @Before("transactionalMethods()") public void beforeTransactionalMethods() { HibernateUtil.beginTransaction(); } @AfterReturning("transactionalMethods()") public void afterReturningTransactionalMethods() { HibernateUtil.commitTransaction(); } @AfterThrowing("transactionalMethods()") public void afterThrowingTransactionalMethods() { HibernateUtil.rollbackTransaction(); } }
この実装では、HibernateパターンとUbiquitous Thread Localパターンを用いてHibernate Session
オブジェクトとTransaction
オブジェクトを管理するものと仮定していますが、JTAベースの実装など、任意の実装を代わりに使うこともできます。
おわりに
本稿では、リソース管理、セキュリティ、トランザクションといった分野横断的な問題をアスペクトとして実装するためにEJB 3.0とJSR 250のアノテーションセットを使いました。ここではいくつかのことを学びました。第一に、具体的なサンプルアスペクトを通じて、AspectJの実装を用いて分野横断的な問題をモジュール化する方法を学びました。第二に、間もなく登場するEJB 3.0の新しい考え方や概念を考察しました。第三に、ビジネスオブジェクトをEJB APIから分離すると大きな自由度が得られることを学びました。例えば、TravelAgencyServiceImpl
をステートレスセッションBeanにするには、次のアノテーションを追加するだけで済みます。
@Stateful public class TravelAgencyServiceImpl implements ITravelAgencyService { ... }
エンタープライズサービスの配備に関して、この極めて自由度の高いアプローチは、フレームワーク/コンテナ業界にさらなる競争と革新をもたらすものと思われます。