68.4. 与 EJB 集成


进程引擎为企业 Java Beans(EJB)提供完整的集成层。这个层支持本地和远程 EJB 互动。

以下模块提供 EJB 服务:

  • jBPM-services-ejb-api :使用特定于 EJB 的接口和对象扩展 jbpm-services-api 模块的 API 模块
  • jBPM-services-ejb-impl:用于核心服务的 EJB 扩展
  • jBPM-services-ejb-timer :基于 EJB Timer 服务的进程引擎调度程序服务实施
  • jBPM-services-ejb-client :用于远程交互的 EJB 远程客户端实施,默认情况下支持 Red Hat JBoss EAP

EJB 层基于流程引擎服务。虽然您使用远程接口,它提供了与核心模块相同的功能。

主要限制会影响部署服务,如果将其用作远程 EJB 服务,则只支持以下方法:

  • deploy()
  • imageink()
  • activate()
  • deactivate()
  • isDeployed()

其他方法将被排除,因为它们返回运行时对象实例,如 RuntimeManager,这无法通过远程接口使用。

所有其他服务都提供与核心模块中包含的版本相同的 EJB 功能。

68.4.1. EJB 服务的实现

作为进程引擎核心服务的扩展,EJB 服务提供基于 EJB 的执行语义,并基于各种特定于 EJB 的功能。

  • DeploymentServiceEJBImpl 作为带有容器管理的并发的 EJB 单例实施。其锁定类型设置为 写入
  • DefinitionServiceEJBImpl 作为带有容器管理的并发的 EJB 单例实施。其整体锁定类型设置为 read,对于 buildProcessDefinition() 方法,锁定类型设置为 write
  • ProcessServiceEJBImpl 作为无状态会话 bean 实现。
  • RuntimeDataServiceEJBImpl 作为 EJB 单例实施。对于多数方法,锁定类型被设置为 读取。对于以下方法,锁定类型被设置为 写入

    • onDeploy()
    • onUnDeploy()
    • onActivate()
    • onDeactivate()
  • UserTaskServiceEJBImpl 作为无状态会话 bean 实现。

Transactions

EJB 容器管理 EJB 服务中的事务。因此,您不需要在应用程序代码中设置任何事务管理器或用户事务。

用户身份提供程序

默认身份提供程序基于 EJBContext 接口,并依赖于名称和角色的调用者主体信息。IdentityProvider 接口提供与角色相关的两种方法:

  • getRoles() 返回空列表,因为 EJBContext 接口不提供获取特定用户的所有角色的选项
  • 具有Role() 委派给上下文的 isCallerInRole() 方法

为确保 EJB 环境可以使用有效信息,您必须遵循标准的 JEE 安全实践来进行身份验证和授权用户。如果没有为 EJB 服务配置验证或授权,则始终假定一个匿名用户。

如果使用不同的安全模型,您可以使用 CDI 样式注入 IdentityProvider 对象用于 EJB 服务。在本例中,创建一个有效的 CDI Bean,它将实现 org.kie.internal.identity.IdentityProvider 接口,并使此 bean 可供您的应用程序注入。这种实施优先于基于 EJBContext的身份提供商。

部署同步

部署同步默认为启用,并且尝试每 3 秒同步任何部署。它作为带有容器管理的并发的 EJB 单例实施。其锁定类型设置为 写入。它使用 EJB 计时器服务来调度同步作业。

EJB 调度程序服务

进程引擎使用调度程序服务来处理基于时间的活动,如计时器事件和期限。在 EJB 环境中运行时,进程引擎使用基于 EJB 计时器服务的调度程序。它为所有 RuntimeManager 实例注册此调度程序。

您可能需要使用特定于应用服务器的配置来支持集群操作。

UserGroupCallbackUserInfo 实现选择

UserGroupCallbackUserInfo 接口所需的实现可能因不同的应用程序而异。这些接口不能直接注入 EJB。您可以使用以下系统属性来选择现有的实现,或使用这些接口的自定义实现流程引擎:

  • org.jbpm.ht.callback :此属性为 UserGroupCallback 接口选择实现:

    • MV EL:默认实施,通常用于测试。
    • LDAP :基于 LDAP 的实施。此实施需要在 jbpm.usergroup.callback.properties 文件中进行额外的配置。
    • db :基于数据库的实施。此实施需要在 jbpm.usergroup.callback.properties 文件中进行额外的配置。
    • JAAS :从容器请求用户信息的实现。
    • props :基于属性的简单回调。这种实施需要额外属性文件,其中包含所有用户和组。
    • 自定义 :一个自定义实施。您必须在 org.jbpm.ht.custom.callback 系统属性中提供实现的完全限定类名称。
  • org.jbpm.ht.userinfo:此属性为 UserInfo 接口选择实现:

    • LDAP :基于 LDAP 的实施。此实施需要在 jbpm-user.info.properties 文件中进行额外的配置。
    • db :基于数据库的实施。此实施需要在 jbpm-user.info.properties 文件中进行额外的配置。
    • props :基于属性的简单实施。这种实施需要包含所有用户信息的额外属性文件。
    • 自定义 :一个自定义实施。您必须在 org.jbpm.ht.custom.userinfo 系统属性中提供实现的完全限定域名。

通常,在应用服务器或 JVM 的启动配置中设置系统属性。在使用服务之前,您还可以在代码中设置属性。例如,您可以提供一个自定义 @Startup bean 来配置这些系统属性。

68.4.2. 本地 EJB 接口

以下本地 EJB 服务接口扩展了核心服务:

  • org.jbpm.services.ejb.api.DefinitionServiceEJBLocal
  • org.jbpm.services.ejb.api.DeploymentServiceEJBLocal
  • org.jbpm.services.ejb.api.ProcessServiceEJBLocal
  • org.jbpm.services.ejb.api.RuntimeDataServiceEJBLocal
  • org.jbpm.services.ejb.api.UserTaskServiceEJBLocal

您必须使用这些接口作为注入点,并使用 @EJB 标注:

使用本地 EJB 服务接口

@EJB
private DefinitionServiceEJBLocal bpmn2Service;

@EJB
private DeploymentServiceEJBLocal deploymentService;

@EJB
private ProcessServiceEJBLocal processService;

@EJB
private RuntimeDataServiceEJBLocal runtimeDataService;
Copy to Clipboard Toggle word wrap

注入这些接口后,在它们上调用操作方式与核心模块相同。使用本地接口不存在限制。

68.4.3. 远程 EJB 接口

以下专用远程 EJB 接口扩展了核心服务:

  • org.jbpm.services.ejb.api.DefinitionServiceEJBRemote
  • org.jbpm.services.ejb.api.DeploymentServiceEJBRemote
  • org.jbpm.services.ejb.api.ProcessServiceEJBRemote
  • org.jbpm.services.ejb.api.RuntimeDataServiceEJBRemote
  • org.jbpm.services.ejb.api.UserTaskServiceEJBRemote

您可以以与本地接口相同的方式使用这些接口,但处理自定义类型除外。

您可以通过两种方式定义自定义类型。全局 定义的类型在应用程序类路径上可用,并包含在企业应用程序中。如果您在 部署单元本地 定义类型,则会在项目依赖项中声明该类型(例如,在 KJAR 文件中),并在部署时解析。

全局可用类型不需要任何特殊处理。EJB 容器在处理远程请求时自动提取数据。但是,默认情况下,本地自定义类型对 EJB 容器不可见。

进程引擎 EJB 服务提供了一种使用自定义类型的机制。它们提供以下额外类型:

  • org.jbpm.services.ejb.remote.api.RemoteObject: a serializable wrapper class for single-value 参数
  • org.jbpm.services.ejb.remote.api.RemoteMap: A dedicated java.util.Map 实现,以简化接受自定义对象输入的服务方法的远程调用。映射的内部实施包含已序列化的内容,以避免在发送时进行额外的序列化。

    这种实现不包括在发送数据时通常不使用的 java.util.Map 的一些方法。

这些特殊对象使用 ObjectInputStream 对象执行大量序列化。它们消除了在 EJB 客户端/容器中对数据进行序列化的需求。因为不需要序列化,所以不需要与 EJB 容器共享自定义数据模型。

以下示例代码适用于本地类型和远程 EJB 服务:

使用带有远程 EJB 服务的本地类型

// Start a process with custom types via remote EJB

Map<String, Object> parameters = new RemoteMap();
Person person = new org.jbpm.test.Person("john", 25, true);
parameters.put("person", person);

Long processInstanceId = processService.startProcess(deploymentUnit.getIdentifier(), "custom-data-project.work-on-custom-data", parameters);

// Fetch task data and complete a task with custom types via remote EJB
Map<String, Object> data = userTaskService.getTaskInputContentByTaskId(taskId);

Person fromTaskPerson = data.get("_person");
fromTaskPerson.setName("John Doe");

RemoteMap outcome = new RemoteMap();
outcome.put("person_", fromTaskPerson);

userTaskService.complete(taskId, "john", outcome);
Copy to Clipboard Toggle word wrap

类似地,您可以使用 RemoteObject 类将事件发送到进程实例:

// Send an event with a custom type via remote EJB
Person person = new org.jbpm.test.Person("john", 25, true);

RemoteObject myObject = new RemoteObject(person);

processService.signalProcessInstance(processInstanceId, "MySignal", myObject);
Copy to Clipboard Toggle word wrap

68.4.4. 远程 EJB 客户端

远程客户端支持通过实施 ClientServiceFactory 接口来提供,该界面是针对应用服务器特定代码的教导:

ClientServiceonnectionFactoryy 接口的 定义

/**
 * Generic service factory used for remote lookups that are usually container specific.
 *
 */
public interface ClientServiceFactory {

	/**
	 * Returns unique name of given factory implementation
	 * @return
	 */
	String getName();

	/**
	 * Returns remote view of given service interface from selected application
	 * @param application application identifier on the container
	 * @param serviceInterface remote service interface to be found
	 * @return
	 * @throws NamingException
	 */
	<T> T getService(String application, Class<T> serviceInterface) throws NamingException;
}
Copy to Clipboard Toggle word wrap

您可以使用 ServiceLoader 机制动态注册实现。默认情况下,红帽 JBoss EAP 中仅提供一个实施。

每个 ClientServiceonnectionFactory y 实施都必须提供名称。此名称用于在客户端 registry 中注册。按名称查找实施。

以下代码获取默认的 Red Hat JBoss EAP 远程客户端:

获取默认的 Red Hat JBoss EAP 远程客户端

// Retrieve a valid client service factory
ClientServiceFactory factory = ServiceFactoryProvider.getProvider("JBoss");

// Set the application variable to the module name
String application = "sample-war-ejb-app";

// Retrieve the required service from the factory
DeploymentServiceEJBRemote deploymentService = factory.getService(application, DeploymentServiceEJBRemote.class);
Copy to Clipboard Toggle word wrap

检索服务后,您可以使用其方法。

使用 Red Hat JBoss EAP 和远程客户端时,您可以添加以下 Maven 依赖项来引入所有 EJB 客户端库:

<dependency>
  <groupId>org.jboss.as</groupId>
  <artifactId>jboss-as-ejb-client-bom</artifactId>
  <version>7.4.14.Final</version> <!-- use the valid version for the server you run on -->
  <optional>true</optional>
  <type>pom</type>
</dependency>
Copy to Clipboard Toggle word wrap
返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat