16.3. カスタムクライアント API を使用した Decision Server のクライアント拡張
Decision Server は、Decision Server サービスの使用時に対話可能な、事前定義済みのクライアント API を使用します。カスタムのクライアント API で Decision Server クライアントを拡張して、ビジネスのニーズに Decision Server サービスを適合させます。
たとえば、以下の手順では、カスタムのクライアント API を Decision Server に追加して、Apache MINA (オープンソースの Java ネットワークアプリケーションフレームワーク) をもとにした、カスタムのデータトランスポートに対応します (このシナリオ向けにすでに設定済み)。
手順
空の Maven プロジェクトを作成して、以下のパッケージタイプと依存関係を、プロジェクトの
pom.xml
ファイルに定義します。サンプルプロジェクトの pom.xml ファイルの例
<packaging>jar</packaging> <properties> <version.org.kie>7.14.0.Final-redhat-00002</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>
以下の例のように、プロジェクトの Java クラスに、関連する
ServicesClient
インターフェイスを実装します。RulesMinaServicesClient
インターフェイスの例public interface RulesMinaServicesClient extends RuleServicesClient { }
インターフェイスをもとにクライアントの実装を登録する必要があるため、特定のインターフェイスが必要です。また、指定のインターフェイスには実装は 1 つしか指定できません。
この例では、カスタムの MINA ベースのデータトランスポートが
Drools
拡張を使用し、このRulesMinaServicesClient
インターフェイスの例は、Drools
拡張から、既存のRuleServicesClient
クライアント API を拡張します。以下の例のように、新規の MINA トランスポートのクライアント機能を追加するのに Decision Server が使用可能な
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(); } } }
この実装例は、以下のデータおよび動作を指定します。
- ソケットベースの通信を使用して簡素化します。
-
Decision Server クライアントのデフォルト設定に依存し、
ServerUrl
を使用して MINA サーバーのホストとポートを提供します。 - マーシャリング形式で JSON を指定します。
-
受信メッセージは左波括弧
{
で始まる JSON オブジェクトでなければなりません。 - 応答の最初の行を待機中に、ブロッキング API と直接、ソケット通信を使用してから、利用可能なすべての行を読み取ります。
- ストリームモード を使用しないので、コマンドの呼び出し後に Decision Server セッションを切断します。
以下の例のように、プロジェクトの Java クラスに
org.kie.server.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; } }
-
新規のクライアント API を Decision Server クライアントで検出できるようにするには、Maven プロジェクトで
META-INF/services/org.kie.server.client.helper.KieServicesClientBuilder
ファイルを作成し、このファイルにKieServicesClientBuilder
実装クラスの完全修飾名を追加します。たとえば、このファイルにはorg.kie.server.ext.mina.client.MinaClientBuilderImpl
の 1 行が含まれます。 -
プロジェクトを構築して、作成された JAR ファイルをプロジェクトの
~/kie-server.war/WEB-INF/lib
ディレクトリーにコピーします。たとえば、Red Hat JBoss EAP ではこのディレクトリーへのパスはEAP_HOME/standalone/deployments/kie-server.war/WEB-INF/lib
です。 Decision Server を起動して、実行中の Decision Server に構築したプロジェクトをデプロイします。プロジェクトは、Decision Central インターフェイスまたは Decision Server REST API (
http://SERVER:PORT/kie-server/services/rest/server/containers/{containerId}
へのPUT
要求) のいずれかを使用してデプロイできます。実行中の Decision Server にプロジェクトをデプロイしたあとに、新規の Decision Server クライアントと対話を開始できます。標準の Decision Server クライアントと同じ方法で、クライアント設定とクライアントインスタンスを作成して、タイプ別にサービスクライアントを取得し、クライアントメソッドを呼び出して、新しいクライアントを使用します。
たとえば、
RulesMinaServiceClient
クライアントインスタンスを作成して、MINA トランスポートを使用して Decision Server で操作を呼び出すことができます。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 トランスポートを使用して Decision Server 上で操作を呼び出す設定例
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());