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());
プロセスエンジンは、トランザクションの同期を登録してセッション状態をクリーンアップするため、セッションを直接破棄すると、トランザクションの完了時に例外が発生します。
67.3.3. トランザクションの再試行
プロセスエンジンがトランザクションのコミット時に別のトランザクションが同時にコミットされることが原因で、コミット操作に失敗することがあります。この場合、プロセスエンジンはトランザクションを再試行する必要があります。
再試行に複数回失敗すると、トランザクションは完全に失敗します。
JVM システムプロパティーを使用して、再試行プロセスを制御できます。
プロパティー | 値 | デフォルト | 説明 |
---|---|---|---|
| Integer | 5 | このプロパティーでは、完全に失敗となる前に、プロセスエンジンがトランザクションを再試行する回数を記述します。 |
| Integer | 50 | 最初の再試行までの時間 (ミリ秒単位)。 |
| Integer | 4 | 後続の再試行ごとに遅延時間を長くする乗数。デフォルト値の場合には、プロセスエンジンは、1 回目の再試行まで 50 ミリ秒、2 番目の再試行まで 200 ミリ秒、3 番目の再試行まで 800 ミリ秒待機します。 |