67.3. プロセスエンジンのトランザクション
プロセスエンジンは、Java Transaction API (JTA) トランザクションをサポートします。
プロセスエンジンの現在のバージョンは、純粋なローカルトランザクションをサポートしません。
アプリケーション内にトランザクション境界を指定しないと、プロセスエンジンは、別のトランザクションでプロセスエンジンで各メソッド呼び出しを自動的に実行します。
必要に応じて、アプリケーションコードでトランザクション境界を指定して、複数のコマンドを 1 つのトランザクションに統合できます。
67.3.1. トランザクションマネージャーの登録
ユーザー定義トランザクションを使用するには、環境でトランザクションマネージャーを登録する必要があります。
以下のサンプルコードはトランザクションマネージャーを登録し、JTA 呼び出しを使用してトランザクション境界を指定します。
トランザクションマネージャーの登録およびトランザクションの使用
// Create the entity manager factory
EntityManagerFactory emf = EntityManagerFactoryManager.get().getOrCreate("org.jbpm.persistence.jpa");
TransactionManager tm = TransactionManagerServices.getTransactionManager();
// Set up the runtime environment
RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get()
.newDefaultBuilder()
.addAsset(ResourceFactory.newClassPathResource("MyProcessDefinition.bpmn2"), ResourceType.BPMN2)
.addEnvironmentEntry(EnvironmentName.TRANSACTION_MANAGER, tm)
.get();
// Get the KIE session
RuntimeManager manager = RuntimeManagerFactory.Factory.get().newPerRequestRuntimeManager(environment);
RuntimeEngine runtime = manager.getRuntimeEngine(ProcessInstanceIdContext.get());
KieSession ksession = runtime.getKieSession();
// Start the transaction
UserTransaction ut = InitialContext.doLookup("java:comp/UserTransaction");
ut.begin();
// Perform multiple commands inside one transaction
ksession.insert( new Person( "John Doe" ) );
ksession.startProcess("MyProcess");
// Commit the transaction
ut.commit();
UserTransaction、TransactionManager、TransactionSynchronizationRegistry などのトランザクション関連のオブジェクトが JNDI に登録されているため、root クラスパスに jndi.properties ファイルを指定して JNDI InitialContextFactory オブジェクトを作成する必要があります。
プロジェクトに jbpm-test モジュールが含まれる場合、このファイルはすでにデフォルトで含まれています。
それ以外の場合は、以下の内容で jndi.properties ファイルを作成してください。
jndi.properties ファイルの内容
java.naming.factory.initial=org.jbpm.test.util.CloseSafeMemoryContextFactory org.osjava.sj.root=target/test-classes/config org.osjava.jndi.delimiter=/ org.osjava.sj.jndi.shared=true
この設定では、simple-jndi:simple-jndi アーティファクトがプロジェクトのクラスパスにあることを前提としています。異なる JNDI 実装を使用することもできます。
デフォルトでは、Narayana JTA トランザクションマネージャーが使用されます。別の JTA トランザクションマネージャーを使用する場合は、persistence.xml ファイルを変更して必要なトランザクションマネージャーを使用できます。たとえば、アプリケーションが Red Hat JBoss EAP バージョン 7 以降で実行する場合は、JBoss トランザクションマネージャーを使用できます。この場合は、persistence.xml ファイルのトランザクションマネージャープロパティーを変更します。
JBoss トランザクションマネージャーの persistence.xml ファイルのトランザクションマネージャープロパティー
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
JTA トランザクション (UserTransaction または CMT) で RuntimeManager クラスの Singleton ストラテジーを使用すると競合状態が作成されます。この競合状態により、Process instance XXX is disconnected と同様のメッセージを含む IllegalStateException 例外が発生する場合があります。
この競合状態を回避するには、ユーザーアプリケーションコードでトランザクションを呼び出す際に、KieSession インスタンスを明示的に同期します。
synchronized (ksession) {
try {
tx.begin();
// use ksession
// application logic
tx.commit();
} catch (Exception e) {
//...
}
}67.3.2. コンテナー管理トランザクションの設定
EJB Bean などの CMT (container-managed transaction) モードで実行するアプリケーションにプロセスエンジンを埋め込む場合は、追加の設定を完了する必要があります。この設定は、アプリケーションが CMT アプリケーションが JNDI から UserTransaction インスタンス (WebSphere Application Server など) にアクセスできないアプリケーションサーバーで実行される場合に特に重要になります。
プロセスエンジンのデフォルトトランザクションマネージャーの実装は、UserTransaction を使用してトランザクションの状態をクエリーし、ステータスを使用してトランザクションを開始するかどうかを判断します。UserTransaction インスタンスにアクセスできない環境では、この実装は失敗します。
CMT 環境で適切な実行を有効にするために、プロセスエンジンは専用のトランザクションマネージャーの実装 (org.jbpm.persistence.jta.ContainerManagedTransactionManager) を提供します。このトランザクションマネージャーはトランザクションがアクティブであることを想定し、getStatus() メソッドが呼び出されると常に ACTIVE を返します。トランザクションマネージャーはコンテナー管理トランザクションモードでこれらの操作に影響を与えることができないため、begin、commit、rollback などの操作は操作できません。
プロセス中にコードはエンジンによって発生した例外をコンテナーに伝播し、コンテナーがトランザクションを必要に応じてロールバックするようにする必要があります。
このトランザクションマネージャーを設定するには、以下の手順を行います。
手順
コードで、セッションを作成または読み込む前に、トランザクションマネージャーと永続コンテキストマネージャーを環境に挿入します。
トランザクションマネージャーと永続コンテキストマネージャーの環境への挿入
Environment env = EnvironmentFactory.newEnvironment(); env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf); env.set(EnvironmentName.TRANSACTION_MANAGER, new ContainerManagedTransactionManager()); env.set(EnvironmentName.PERSISTENCE_CONTEXT_MANAGER, new JpaProcessPersistenceContextManager(env)); env.set(EnvironmentName.TASK_PERSISTENCE_CONTEXT_MANAGER, new JPATaskPersistenceContextManager(env));
persistence.xmlファイルで、JPA プロバイダーを設定します。以下の例では、hibernateおよび WebSphere Application Server を使用します。persistence.xmlファイルでの JPA プロバイダーの設定<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/> <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.WebSphereJtaPlatform"/>
KIE セッションを破棄する場合は、直接破棄しないでください。代わりに、
org.jbpm.persistence.jta.ContainerManagedTransactionDisposeCommandコマンドを実行します。このコマンドは、現在のトランザクションの完了時にセッションが確実に破棄されるようにします。以下の例のksessionは、破棄するKieSessionオブジェクトです。ContainerManagedTransactionDisposeCommandコマンドを使用した KIE セッションの破棄ksession.execute(new ContainerManagedTransactionDisposeCommand());
プロセスエンジンは、トランザクションの同期を登録してセッション状態をクリーンアップするため、セッションを直接破棄すると、トランザクションの完了時に例外が発生します。