搜索

21.3. 使用自定义客户端 API 扩展 KIE 服务器客户端

download PDF

KIE 服务器使用预定义的客户端 API,您可以与之交互以使用 KIE 服务器服务。您可以使用自定义客户端 API 扩展 KIE 服务器客户端,以满足您的业务需求。

例如,这个步骤将自定义客户端 API 添加到 KIE 服务器,以适应自定义数据传输(之前为本情景)基于 Apache MINA(开源 Java 网络应用程序框架)。

流程

  1. 创建一个空的 Maven 项目,并在项目的 pom.xml 文件中定义以下打包类型和依赖项:

    示例项目中的 pom.xml 文件示例

    <packaging>jar</packaging>
    
    <properties>
       <version.org.kie>7.67.0.Final-redhat-00024</version.org.kie>
     </properties>
    
     <dependencies>
       <dependency>
         <groupId>org.kie.server</groupId>
         <artifactId>kie-server-api</artifactId>
         <version>${version.org.kie}</version>
       </dependency>
       <dependency>
          <groupId>org.kie.server</groupId>
          <artifactId>kie-server-client</artifactId>
          <version>${version.org.kie}</version>
        </dependency>
       <dependency>
         <groupId>org.drools</groupId>
         <artifactId>drools-compiler</artifactId>
         <version>${version.org.kie}</version>
       </dependency>
     </dependencies>

  2. 在项目中的 Java 类中实施相关的 ServicesClient 接口,如下例所示:

    RulesMinaServicesClient 接口示例

    public interface RulesMinaServicesClient extends RuleServicesClient {
    
    }

    需要特定的接口,因为您必须基于接口注册客户端实施,而且只能有一个给定接口的实施。

    在本例中,基于自定义 MINA 的数据传输使用 Drools 扩展,因此本例 RulesMinaServicesClient 接口扩展了 Drools 扩展中现有的 RuleServicesClient 客户端 API。

  3. 实施 KIE 服务器可以用来为新的 MINA 传输提供额外客户端功能的 RulesMinaServicesClient 接口,如下例所示:

    RulesMinaServicesClient 接口的实现示例

    public class RulesMinaServicesClientImpl implements RulesMinaServicesClient {
    
        private String host;
        private Integer port;
    
        private Marshaller marshaller;
    
        public RulesMinaServicesClientImpl(KieServicesConfiguration configuration, ClassLoader classloader) {
            String[] serverDetails = configuration.getServerUrl().split(":");
    
            this.host = serverDetails[0];
            this.port = Integer.parseInt(serverDetails[1]);
    
            this.marshaller = MarshallerFactory.getMarshaller(configuration.getExtraJaxbClasses(), MarshallingFormat.JSON, classloader);
        }
    
        public ServiceResponse<String> executeCommands(String id, String payload) {
    
            try {
                String response = sendReceive(id, payload);
                if (response.startsWith("{")) {
                    return new ServiceResponse<String>(ResponseType.SUCCESS, null, response);
                } else {
                    return new ServiceResponse<String>(ResponseType.FAILURE, response);
                }
            } catch (Exception e) {
                throw new KieServicesException("Unable to send request to KIE Server", e);
            }
        }
    
        public ServiceResponse<String> executeCommands(String id, Command<?> cmd) {
            try {
                String response = sendReceive(id, marshaller.marshall(cmd));
                if (response.startsWith("{")) {
                    return new ServiceResponse<String>(ResponseType.SUCCESS, null, response);
                } else {
                    return new ServiceResponse<String>(ResponseType.FAILURE, response);
                }
            } catch (Exception e) {
                throw new KieServicesException("Unable to send request to KIE Server", e);
            }
        }
    
        protected String sendReceive(String containerId, String content) throws Exception {
    
            // Flatten the content to be single line:
            content = content.replaceAll("\\n", "");
    
            Socket minaSocket = null;
            PrintWriter out = null;
            BufferedReader in = null;
    
            StringBuffer data = new StringBuffer();
            try {
                minaSocket = new Socket(host, port);
                out = new PrintWriter(minaSocket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(minaSocket.getInputStream()));
    
                // Prepare and send data:
                out.println(containerId + "|" + content);
                // Wait for the first line:
                data.append(in.readLine());
                // Continue as long as data is available:
                while (in.ready()) {
                    data.append(in.readLine());
                }
    
                return data.toString();
            } finally {
                out.close();
                in.close();
                minaSocket.close();
            }
        }
    }

    这个实现示例指定了以下数据和行为:

    • 使用基于套接字的通讯进行简单性
    • 依赖于 KIE 服务器客户端的默认配置,并使用 ServerUrl 提供 MINA 服务器的主机和端口
    • 将 JSON 指定为 marshalling 格式
    • 需要接收消息作为以 open bracket {开头的 JSON 对象
    • 在等待响应的第一行时,使用直接套接字与阻塞 API 通信,然后读取所有可用的行
    • 不要使用 流模式, 因此在调用命令后断开 KIE 服务器会话
  4. 在项目中的 Java 类中实施 org.kie.client.client.helper.KieServicesClientBuilder 接口,如下例所示:

    KieServicesClientBuilder 接口的实现示例

    public class MinaClientBuilderImpl implements KieServicesClientBuilder {  1
    
        public String getImplementedCapability() {  2
            return "BRM-Mina";
        }
    
        public Map<Class<?>, Object> build(KieServicesConfiguration configuration, ClassLoader classLoader) {  3
            Map<Class<?>, Object> services = new HashMap<Class<?>, Object>();
    
            services.put(RulesMinaServicesClient.class, new RulesMinaServicesClientImpl(configuration, classLoader));
    
            return services;
        }
    
    }

    1
    可让您向通用 KIE 服务器客户端基础架构提供额外的客户端 API
    2
    定义客户端使用的 KIE 服务器功能(extension)
    3
    提供客户端实施的映射,其中键是接口,值是完全初始化的实现
  5. 要使新客户端 API 发现 KIE 服务器客户端,请在 文件中创建一个 META-INF/services/org.kie.client.client.helper. KieServicesClientBuilder 文件,并在文件中添加完全限定的类名称。在本例中,该文件包含一行 org.kie.server.ext.mina.client.MinaClientBuilderImpl
  6. 构建您的项目,并将生成的 JAR 文件复制到项目的 ~/kie-server.war/WEB-INF/lib 目录中。例如,在红帽 JBoss EAP 上,此目录的路径是 EAP_HOME/standalone/deployments/kie-server.war/WEB-INF/lib
  7. 启动 KIE 服务器并将构建的项目部署到正在运行的 KIE 服务器中。您可以使用 Business Central 接口或 KIE 服务器 REST API 部署项目( PUT 请求到 http://SERVER:PORT/kie-server/services/rest/server/containers/{containerId})。

    在某个正在运行的 KIE 服务器上部署项目后,您可以开始与新的 KIE 服务器客户端交互。您可以采用与标准 KIE 服务器客户端相同的方法,创建客户端配置和客户端实例,并通过类型检索服务客户端,以及调用客户端方法。

    在本例中,您可以创建一个 RulesMinaServiceClient 客户端实例,并通过 MINA 传输调用 KIE 服务器上的操作:

    创建 RulesMinaServiceClient 客户端的实现示例

    protected RulesMinaServicesClient buildClient() {
        KieServicesConfiguration configuration = KieServicesFactory.newRestConfiguration("localhost:9123", null, null);
        List<String> capabilities = new ArrayList<String>();
        // Explicitly add capabilities (the MINA client does not respond to `get-server-info` requests):
        capabilities.add("BRM-Mina");
    
        configuration.setCapabilities(capabilities);
        configuration.setMarshallingFormat(MarshallingFormat.JSON);
    
        configuration.addJaxbClasses(extraClasses);
    
        KieServicesClient kieServicesClient =  KieServicesFactory.newKieServicesClient(configuration);
    
        RulesMinaServicesClient rulesClient = kieServicesClient.getServicesClient(RulesMinaServicesClient.class);
    
        return rulesClient;
    }

    通过 MINA 传输调用 KIE 服务器操作的示例配置

    RulesMinaServicesClient rulesClient = buildClient();
    
    List<Command<?>> commands = new ArrayList<Command<?>>();
    BatchExecutionCommand executionCommand = commandsFactory.newBatchExecution(commands, "defaultKieSession");
    
    Person person = new Person();
    person.setName("mary");
    commands.add(commandsFactory.newInsert(person, "person"));
    commands.add(commandsFactory.newFireAllRules("fired"));
    
    ServiceResponse<String> response = rulesClient.executeCommands(containerId, executionCommand);
    Assert.assertNotNull(response);
    
    Assert.assertEquals(ResponseType.SUCCESS, response.getType());
    
    String data = response.getResult();
    
    Marshaller marshaller = MarshallerFactory.getMarshaller(extraClasses, MarshallingFormat.JSON, this.getClass().getClassLoader());
    
    ExecutionResultImpl results = marshaller.unmarshall(data, ExecutionResultImpl.class);
    Assert.assertNotNull(results);
    
    Object personResult = results.getValue("person");
    Assert.assertTrue(personResult instanceof Person);
    
    Assert.assertEquals("mary", ((Person) personResult).getName());
    Assert.assertEquals("JBoss Community", ((Person) personResult).getAddress());
    Assert.assertEquals(true, ((Person) personResult).isRegistered());

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

© 2024 Red Hat, Inc.