68.3. Spring との統合

Spring フレームワークでプロセスエンジンを使用する方法はいくつかありますが、最も頻繁に使用されるのは 2 つのアプローチです。

  • Runtime Manager API の直接使用
  • プロセスエンジンサービスの使用

どちらのアプローチもテストされ、有効です。

アプリケーションが 1 つのランタイムマネージャーのみを使用する必要がある場合は、ダイレクト Runtime Manager API を使用します。これは、Spring アプリケーションでプロセスエンジンを使用する最も簡単な方法となるためです。

アプリケーションがランタイムマネージャーの複数のインスタンスを使用する必要がある場合は、プロセスエンジンサービスを使用して、動的ランタイム環境を提供することでベストプラクティスをカプセル化します。

68.3.1. Spring でのランタイムマネージャー API の直接使用

ランタイムマネージャーは、プロセスエンジンとタスクサービスを同期して管理します。ランタイムマネージャーの詳細は、「ランタイムマネージャー」を参照してください。

Spring フレームワークでランタイムマネージャーを設定するには、以下のファクトリー Bean を使用します。

  • org.kie.spring.factorybeans.RuntimeEnvironmentFactoryBean
  • org.kie.spring.factorybeans.RuntimeManagerFactoryBean
  • org.kie.spring.factorybeans.TaskServiceFactoryBean

これらのファクトリー Bean は、Spring アプリケーションの spring.xml ファイルを設定する標準的な方法を提供します。

68.3.1.1. RuntimeEnvironmentFactoryBean Bean

RuntimeEnvironmentFactoryBean ファクトリー Bean は RuntimeEnvironment のインスタンスを生成します。これらのインスタンスは、RuntimeManager インスタンスの作成に必要です。

Bean は、異なるデフォルト設定を持つ以下のタイプの RuntimeEnvironment インスタンスの作成をサポートします。

  • DEFAULT: ランタイムマネージャーのデフォルトまたは最も一般的な設定
  • EMPTY: 手動で設定できる、完全に空の環境
  • DEFAULT_IN_MEMORY: ランタイムエンジンの永続性がない DEFAULT と同じ設定
  • DEFAULT_KJAR: DEFAULT と同じ設定ですが、アセットは KJAR アーティファクトから読み込まれます。これは、リリース ID または GAV 値によって識別されます。
  • DEFAULT_KJAR_CL: 設定は KJAR アーティファクトの kmodule.xml 記述子から構築されます。

必須プロパティーは選択されたタイプによって異なります。ただし、全タイプに対するナレッジ情報が必要です。この要件は、以下のいずれかの情報が提供される必要があることを意味します。

  • knowledgeBase
  • assets
  • releaseId
  • groupId, artifactId, version

タイプ DEFAULTDEFAULT_KJAR、および DEFAULT_KJAR_CL については、以下のパラメーターを指定して永続性を設定する必要もあります。

  • エンティティーマネージャーファクトリー
  • トランザクションマネージャー

永続性やトランザクションサポートがこのトランザクションマネージャーを基に設定されるため、トランザクションマネージャーは Spring トランザクションマネージャーである必要があります。

任意で、EntityManagerFactory から新規インスタンスを作成する代わりに EntityManager インスタンスを指定できます。たとえば、Spring から共有エンティティーマネージャーを使用できます。

その他のプロパティーはすべて任意です。ランタイム環境の選択したタイプで決定されるデフォルト値を上書きできます。

68.3.1.2. RuntimeManagerFactoryBean Bean

RuntimeManagerFactoryBean ファクトリー Bean は、提供された RuntimeEnvironment インスタンスに基づいて、指定したタイプの RuntimeManager インスタンスを生成します。

サポートされるタイプは、ランタイムマネージャーの戦略に対応します。

  • SINGLETON
  • PER_REQUEST
  • PER_PROCESS_INSTANCE

タイプが指定されていない場合のデフォルトタイプは SINGLETON です。

すべてのランタイムマネージャーは一意に特定する必要があるため、識別子は必須プロパティーです。このファクトリーによって作成されたすべてのインスタンスがキャッシュされるため、destroy メソッド (close()) を使用して適切に破棄できます。

68.3.1.3. TaskServiceFactoryBean Bean

TaskServiceFactoryBean ファクトリー Bean は、指定のプロパティーに基づいて TaskService のインスタンスを生成します。以下の必須プロパティーを指定する必要があります。

  • エンティティーマネージャーファクトリー
  • トランザクションマネージャー

永続性やトランザクションサポートがこのトランザクションマネージャーを基に設定されるため、トランザクションマネージャーは Spring トランザクションマネージャーである必要があります。

任意で、EntityManagerFactory から新規インスタンスを作成する代わりに EntityManager インスタンスを指定できます。たとえば、Spring から共有エンティティーマネージャーを使用できます。

タスクサービスインスタンスに、任意の追加プロパティーを設定することもできます。

  • userGroupCallback: タスクサービスが使用する必要のある UserGroupCallback の実装。デフォルト値は MVELUserGroupCallbackImpl です。
  • userInfo: タスクサービスが使用する必要のある UserInfo の実装。デフォルト値は DefaultUserInfo です。
  • listener: タスクのさまざまな操作で通知する必要がある TaskLifeCycleEventListener リスナーのリスト

このファクトリー Bean は、タスクサービスの単一のインスタンスを作成します。設計上、このインスタンスは Spring 環境のすべての Bean 間で共有される必要があります。

68.3.1.4. Spring アプリケーションを使用したランタイムマネージャーの設定

以下の手順は、Spring アプリケーション内の単一のランタイムマネージャーの完全な設定例になります。

手順

  1. エンティティーマネージャーファクトリーおよびトランザクションマネージャーを設定します。

    spring.xml ファイルでのエンティティーマネージャーファクトリーおよびトランザクションマネージャーの設定

    <bean id="jbpmEMF" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <property name="persistenceUnitName" value="org.jbpm.persistence.spring.jta"/>
    </bean>
    
    <bean id="jbpmEM" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
      <property name="entityManagerFactory" ref="jbpmEMF"/>
    </bean>
    
    <bean id="narayanaUserTransaction" factory-method="userTransaction" class="com.arjuna.ats.jta.UserTransaction" />
    
    <bean id="narayanaTransactionManager" factory-method="transactionManager" class="com.arjuna.ats.jta.TransactionManager" />
    
    <bean id="jbpmTxManager" class="org.springframework.transaction.jta.JtaTransactionManager">
      <property name="transactionManager" ref="narayanaTransactionManager" />
      <property name="userTransaction" ref="narayanaUserTransaction" />
    </bean>

    これらの設定は、以下の永続性設定を定義します。

    • JTA トランザクションマネージャー (Narayana JTA でサポート) (ユニットテスト用またはサーブレットコンテナー用)
    • org.jbpm.persistence.spring.jta 永続ユニットのエンティティーマネージャーファクトリー
  2. ビジネスプロセスリソースを設定します。

    spring.xml ファイルでのビジネスプロセスリソースの設定

    <bean id="process" factory-method="newClassPathResource" class="org.kie.internal.io.ResourceFactory">
      <constructor-arg>
        <value>jbpm/processes/sample.bpmn</value>
      </constructor-arg>
    </bean>

    これらの設定は、実行可能な 1 つのプロセスを定義します。リソースの名前は sample.bpmn で、クラスパスで利用可能でなければなりません。クラスパスを単純な方法で使用して、プロセスエンジンを試すためのリソースを追加できます。

  3. エンティティーマネージャー、トランザクションマネージャー、およびリソースを使用して RuntimeEnvironment インスタンスを設定します。

    spring.xml ファイルでの RuntimeEnvironment インスタンスの設定

    <bean id="runtimeEnvironment" class="org.kie.spring.factorybeans.RuntimeEnvironmentFactoryBean">
      <property name="type" value="DEFAULT"/>
      <property name="entityManagerFactory" ref="jbpmEMF"/>
      <property name="transactionManager" ref="jbpmTxManager"/>
      <property name="assets">
        <map>
          <entry key-ref="process"><util:constant static-field="org.kie.api.io.ResourceType.BPMN2"/></entry>
        </map>
      </property>
    </bean>

    これらの設定は、ランタイムマネージャーのデフォルトのランタイム環境を定義します。

  4. 環境に基づいて RuntimeManager インスタンスを作成します。

    <bean id="runtimeManager" class="org.kie.spring.factorybeans.RuntimeManagerFactoryBean" destroy-method="close">
      <property name="identifier" value="spring-rm"/>
      <property name="runtimeEnvironment" ref="runtimeEnvironment"/>
    </bean>

結果

これらの手順を完了した後、EntityManagerFactory クラスおよび JTA トランザクションマネージャーを使用して、ランタイムマネージャーを使用して Spring 環境でプロセスを実行できます。

リポジトリー では、異なるストラテジーの完全 Spring 設定ファイルを確認できます。

68.3.1.5. Spring フレームワークのランタイムマネージャーの追加設定オプション

「Spring アプリケーションを使用したランタイムマネージャーの設定」で説明されているように、EntityManagerFactory クラスと JTA トランザクションマネージャーの設定の他に、Spring フレームワークのランタイムマネージャーに他の設定オプションを使用できます。

  • JTA および SharedEntityManager クラス
  • ローカル永続ユニットおよび EntityManagerFactory クラス
  • ローカル永続ユニットおよび SharedEntityManager クラス

アプリケーションがローカル永続ユニットで設定され、AuditService サービスを使用してプロセスエンジン履歴データをクエリーする場合は、org.kie.api.runtime.EnvironmentName.USE_LOCAL_TRANSACTIONS 環境エントリーを RuntimeEnvironment インスタンス設定に追加する必要があります。

spring.xml ファイルのローカル永続ユニットの RuntimeEnvironment インスタンス設定

<bean id="runtimeEnvironment" class="org.kie.spring.factorybeans.RuntimeEnvironmentFactoryBean">
...
    <property name="environmentEntries" ref="env" />
  </bean>
  ...

  <util:map id="env" key-type="java.lang.String" value-type="java.lang.Object">
		<entry>
			<key>
				<util:constant
					static-field="org.kie.api.runtime.EnvironmentName.USE_LOCAL_TRANSACTIONS" />
			</key>
			<value>true</value>
		</entry>
	</util:map>

リポジトリーの設定オプションの例は、設定ファイル および テストケース で確認できます。

68.3.2. Spring を使用したプロセスエンジンサービス

動的な Spring アプリケーションを作成し、アプリケーションを再起動しなくても、プロセス定義、データモデル、ルール、フォームなどのビジネスアセットを追加および削除できます。

この場合は、プロセスエンジンサービスを使用します。プロセスエンジンサービスはフレームワークに依存しないように設計され、必要なフレームワーク固有のアドオンに個別のモジュールが追加されます。

jbpm-kie-services モジュールには、サービスのコードロジックが含まれます。Spring アプリケーションはこれらの純粋な Java サービスを使用できます。

プロセスエンジンサービスを設定するために Spring アプリケーションに追加する必要がある唯一のコードは、IdentityProvider インターフェイスの実装です。この実装は、セキュリティー設定によって異なります。以下の実装例では Spring Security を使用していますが、Spring アプリケーションで利用可能なすべてのセキュリティー機能に対応していない可能性があります。

Spring Security を使用した IdentityProvider インターフェイスの実装

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.kie.internal.identity.IdentityProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

public class SpringSecurityIdentityProvider implements IdentityProvider {

	public String getName() {

		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		if (auth != null && auth.isAuthenticated()) {
			return auth.getName();
		}
		return "system";
	}

	public List<String> getRoles() {
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		if (auth != null && auth.isAuthenticated()) {
			List<String> roles = new ArrayList<String>();

			for (GrantedAuthority ga : auth.getAuthorities()) {
				roles.add(ga.getAuthority());
			}

			return roles;
		}

		return Collections.emptyList();
	}

	public boolean hasRole(String role) {
		return false;
	}

}

68.3.2.1. Spring アプリケーションを使用したプロセスエンジンサービスの設定

以下の手順は、Spring アプリケーション内のプロセスエンジンサービスの完全な設定例です。

手順

  1. トランザクションを設定します。

    spring.xml ファイルでのトランザクションの設定

    <context:annotation-config />
    <tx:annotation-driven />
    <tx:jta-transaction-manager />
    
    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

  2. JPA および永続性を設定します。

    spring.xml ファイルでの JPA および永続性の設定

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="transactionManager">
       <property name="persistenceXmlLocation" value="classpath:/META-INF/jbpm-persistence.xml" />
    </bean>

  3. セキュリティーおよびユーザーおよびグループの情報プロバイダーを設定します。

    spring.xml ファイルでのセキュリティー、ユーザー、およびグループの情報プロバイダーの設定

    <util:properties id="roleProperties" location="classpath:/roles.properties" />
    
    <bean id="userGroupCallback" class="org.jbpm.services.task.identity.JBossUserGroupCallbackImpl">
      <constructor-arg name="userGroups" ref="roleProperties"></constructor-arg>
    </bean>
    
    <bean id="identityProvider" class="org.jbpm.spring.SpringSecurityIdentityProvider"/>

  4. ランタイムマネージャーファクトリーを設定します。このファクトリーは Spring コンテキストを認識するため、トランザクションコマンドサービスやタスクサービスなどの必要なサービスをサポートすることで Spring コンテナーと正しい方法で対話できます。

    spring.xml ファイルでのランタイムマネージャーファクトリーの設定

    <bean id="runtimeManagerFactory" class="org.kie.spring.manager.SpringRuntimeManagerFactoryImpl">
      <property name="transactionManager" ref="transactionManager"/>
      <property name="userGroupCallback" ref="userGroupCallback"/>
    </bean>
    
    <bean id="transactionCmdService" class="org.jbpm.shared.services.impl.TransactionalCommandService">
      <constructor-arg name="emf" ref="entityManagerFactory"></constructor-arg>
    </bean>
    
    <bean id="taskService" class="org.kie.spring.factorybeans.TaskServiceFactoryBean" destroy-method="close">
      <property name="entityManagerFactory" ref="entityManagerFactory"/>
      <property name="transactionManager" ref="transactionManager"/>
      <property name="userGroupCallback" ref="userGroupCallback"/>
      <property name="listeners">
        <list>
          <bean class="org.jbpm.services.task.audit.JPATaskLifeCycleEventListener">
            <constructor-arg value="true"/>
          </bean>
        </list>
      </property>
    </bean>

  5. プロセスエンジンサービスを Spring Bean として設定します。

    spring.xml ファイルでプロセスエンジンサービスを Spring Bean として設定

    <!-- Definition service -->
    <bean id="definitionService" class="org.jbpm.kie.services.impl.bpmn2.BPMN2DataServiceImpl"/>
    
    <!-- Runtime data service -->
    <bean id="runtimeDataService" class="org.jbpm.kie.services.impl.RuntimeDataServiceImpl">
      <property name="commandService" ref="transactionCmdService"/>
      <property name="identityProvider" ref="identityProvider"/>
      <property name="taskService" ref="taskService"/>
    </bean>
    
    <!-- Deployment service -->
    <bean id="deploymentService" class="org.jbpm.kie.services.impl.KModuleDeploymentService" depends-on="entityManagerFactory" init-method="onInit">
      <property name="bpmn2Service" ref="definitionService"/>
      <property name="emf" ref="entityManagerFactory"/>
      <property name="managerFactory" ref="runtimeManagerFactory"/>
      <property name="identityProvider" ref="identityProvider"/>
      <property name="runtimeDataService" ref="runtimeDataService"/>
    </bean>
    
    <!-- Process service -->
    <bean id="processService" class="org.jbpm.kie.services.impl.ProcessServiceImpl" depends-on="deploymentService">
      <property name="dataService" ref="runtimeDataService"/>
      <property name="deploymentService" ref="deploymentService"/>
    </bean>
    
    <!-- User task service -->
    <bean id="userTaskService" class="org.jbpm.kie.services.impl.UserTaskServiceImpl" depends-on="deploymentService">
      <property name="dataService" ref="runtimeDataService"/>
      <property name="deploymentService" ref="deploymentService"/>
    </bean>
    
    <!-- Register the runtime data service as a listener on the deployment service so it can receive notification about deployed and undeployed units -->
    <bean id="data" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="deploymentService">
      <property name="targetObject" ref="deploymentService"></property>
      <property name="targetMethod"><value>addListener</value></property>
      <property name="arguments">
      <list>
          <ref bean="runtimeDataService"/>
      </list>
      </property>
    </bean>

結果

Spring アプリケーションはプロセスエンジンサービスを使用できます。