HOME    BRMSブログ  No.25 Corticon ServerのAPIを利用してディシジョン・サービスをバッチデプロイする

BRMS徹底活用ブログ

No.25 Corticon ServerのAPIを利用してディシジョン・サービスをバッチデプロイする

2018.01.31 Progress Corticon

本エントリーは株式会社アシスト様が寄稿したエントリー(https://www.ashisuto.co.jp/product/category/brms/progress_corticon/column/detail/brmstech25.html)を転載したものとなります。

No.25 Corticon ServerのAPIを利用してディシジョン・サービスをバッチデプロイする(2018年2月2日)

Corticon Studioで作成したルールアセット(語彙ファイル、ルールシートファイル、ルールフローファイルの一式)を、ディシジョン・サービスとして利用するには、これらのファイルをプリコンパイル(※)したファイル(EDS)を作成し、Corticon Serverにデプロイしなければなりません。

Corticon Serverへルールアセットのデプロイは主に次の方法が用意されています。

これらの方法の詳細に関しましては、製品に付属しているマニュアルにそれぞれ詳細が記載されています。それぞれの方法を組み合わせることもできますので、運用場面によって、柔軟にディシジョン・サービスのデプロイ手順を検討することができるようになっています。しかし、上記に挙げた方法は、運用方針として統制がとりにくかったり、手作業が必要なステップがあったり、どれも一長一短があります。

そこで、今回の記事では、Corticon ServerのAPIを利用してディシジョン・サービスをデプロイする方法を紹介します。Javaプログラムの実装が必要ですが、この方法であれば、ディシジョン・サービスのデプロイ作業の完全な自動化が可能です。

  • このプリコンパイルとは、通常のプログラム言語等のプリコンパイルとは異なり、ルールアセットを元ににデプロイするための特殊なファイル(ファイル)を作成するという意味です。製品内ではその作業のことをプリコンパイルという用語で統一していますので、本記事内でもプリコンパイルと記述します。


[記事執筆環境]
Corticon 5.6.1

ディシジョン・サービスのデプロイプログラムの要件

ディシジョン・サービスをCorticon Serverにデプロイするプログラムの要件としては、以下を想定しています。

この要件を図で表現すると以下になります。

画像1

この要件を実現するJavaで作成したディシジョン・サービスのデプロイプログラムを以下で紹介します。

ディシジョン・サービスのデプロイプログラムの本体

まず、作成したJavaプログラムの全体を以下に示します。

<Javaプログラム全体>


ppackage deployTest;

import java.io.File;
import java.nio.file.*;

import com.corticon.eclipse.soap.CcMessageHandler;
import com.corticon.eclipse.studio.deployment.swing.CcDeployFactory;
import com.corticon.eclipse.studio.deployment.swing.ICcDeploy;

public class sample {
	private static String ERF_DIR = "C:/tmp";
	private static String CCSERVER_URL = 
			"https://nnn.nnn.nnn.nnn:8080/axis/services/CorticonAdmin";
	private static String WIN_NET_DRV = "Y:/";
	private static String LINUX_MNT_DIR = "/home/tani/fugafuga/";

	public static void main(String[] args) {
		precompileRuleFile();
		copyEdsFile();
		deployRemoteServer();
	}

	private static void precompileRuleFile() {
		try {
			// ICcServer iCcServer = CcServerFactory.getCcServer();
			ICcDeploy iCcDeploy = CcDeployFactory.newDeployment();

			File[] files = new File(ERF_DIR).listFiles();
			for (File f : files) {
				if (f.getPath().endsWith(".erf") != true) continue;

				String dsName = f.getName().replace(".erf", "");

				// プリコンパイル実行
				String edsPath = iCcDeploy.precompileDecisionService(
						f.getPath(), dsName, ERF_DIR, true);
				System.out.println("EDSファイルを作成: " + edsPath);
			}
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

	private static void copyEdsFile() {
		try {
			// ローカルのedsをネットワークドライブに割り当てたWindowsファイル共有サーバーにコピー。
			File[] files = new File(ERF_DIR).listFiles();
			for (File f : files) {
				if (f.getPath().endsWith(".eds") != true) continue;

				Path pathFrom = Paths.get(f.getPath());
				Path pathTo = Paths.get(WIN_NET_DRV + f.getName());
				Files.copy(pathFrom, pathTo, StandardCopyOption.REPLACE_EXISTING);
				System.out.println("Copy From: " + f.getPath() + 
						", To: " + WIN_NET_DRV + f.getName());
			}
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

	private static void deployRemoteServer() {
		try {
			String response;
			File[] files = new File(ERF_DIR).listFiles();
			for (File f : files) {
				if (f.getPath().endsWith(".eds") != true) continue;

				String dsName = f.getName().split("_")[0];

				// デプロイ済みのディジョン・サービス一覧をチェックし、すでに存在していれば削除
				if (getDsNamesRPC().contains(dsName)) {
					response = CcMessageHandler.executeRPC(CCSERVER_URL,
							"removeDecisionService",
							new Object[] {dsName});
					System.out.println(dsName + " を削除: " + response);
				}

				// ディシジョン・サービスをデプロイ
				response = CcMessageHandler.executeRPC(CCSERVER_URL,
					"addDecisionService3",
					new Object[] {dsName, LINUX_MNT_DIR + f.getName(), false});
				System.out.println(dsName + " をデプロイ: " + response);
			}

			System.out.println("デプロイ済みディシジョン・サービス一覧: " + getDsNamesRPC());
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

	// デプロイ済みディシジョン・サービス一覧を取得
	private static String getDsNamesRPC() {
		String response = "";
		try {
			response = CcMessageHandler.executeRPC(CCSERVER_URL,
					"getDecisionServiceNames",
					new Object[] {});
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return response;
	}
}

このJavaプログラムを実行するには、クラスパス(EclipseのJavaプロジェクトの参照)に、プログレス社が提供しているPROGRESS_CORTICON_SERVER_UTILSに入っているライブラリ一式を追加する必要があります。Eclipseで参照ライブラリーの追加の設定を行うと、以下のような画面になります。

<参照ライブラリー追加後の画面>

画像2

また、このプログラムを実行するには、JDKのlibに含まれているtools.jarが必要です。プログラム実行環境のJREには、JDKのtools.jarをコピーしてJRE\lib\ext\ 以下に配置してください。

プログラムをJARにエクスポートするかEclipseのテスト実行機能で実行すると、以下のような動作を行います。

以下で、プログラム内容の詳細な解説を行います。

プログラム内容の解説

■ precompileRuleFile

<precompileRuleFile>


	private static void precompileRuleFile() {
		try {
			// ICcServer iCcServer = CcServerFactory.getCcServer();
			ICcDeploy iCcDeploy = CcDeployFactory.newDeployment();

			File[] files = new File(ERF_DIR).listFiles();
			for (File f : files) {
				if (f.getPath().endsWith(".erf") != true) continue;

				String dsName = f.getName().replace(".erf", "");

				// プリコンパイル実行
				String edsPath = iCcDeploy.precompileDecisionService(
						f.getPath(), dsName, ERF_DIR, true);
				System.out.println("EDSファイルを作成: " + edsPath);
			}
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

このプログラムprecompileRuleFileでは、対象のルールフロー(.erfファイル)が、全てERF_DIR(C:\tmp\)直下にあることが前提となっています。
注意点として、ルールフロー(.erfファイル)は、内部に語彙(.ecoreファイル)やルールシート(.ersファイル)への相対パスを保存しており、その相対パスに語彙やルールシートが配置されていないといけません。したがって、Corticon Studioで作成したルールフロー(.erfファイル)をERF_DIR(C:\tmp\)にコピーする場合は、相対パスの関係が崩れないように、語彙(.ecoreファイル)やルール(.ersファイル)もERF_DIR(C:\tmp\)にコピーする必要があります。

次に、このプログラムprecompileRuleFileでは、プロジェクトの参照設定に追加した、Corticon Serverのライブラリ内にあるAPIを直接使用しています。
ルールのプリコンパイルはprecompileDecisionService()メソッドを使用します。precompileDecisionService()メソッドは、Corticon Server本体のインターフェースであるICcServerと、ルールのプリコンパイルなどに特化したインターフェースICcDeployの、両方で使用可能です。

しかし、ICcServerを利用するにはCorticon Server本体を起動しないといけないため、このプログラムではICcDeployを使用しています。(ICcServerは3行目でコメントアウトしています。)
precompileDecisionService()メソッドは第1引数にルールフローファイル(erf)のパス文字列、第2引数にディシジョン・サービス名、第3引数にEDSファイルの出力先フォルダ、第4引数にEDSファイルを上書き保存するかどうかの真偽値をとり、生成したEDSファイルのパス文字列を返します。ここではディシジョン・サービス名をルールフローファイル名にしていますが、全く別の名前にすることもできます。precompileDecisionService()メソッドのより詳細な説明や引数の仕様に関しては、Corticonに付属するICcServerかICcDeployのJavaDocをご確認ください。

例えば、ERF_DIR(C:\tmp\)以下に「test.erf」, 「ルールフロー.erf」という2個のerfファイルを置き、それぞれ必要なecoreファイル, ersファイルを正しいパスに配置すると、precompileRuleFileの動作結果としては以下になります。

<precompileRuleFile実行結果>


EDSファイルを作成: C:/tmp/test_v1_0.eds
EDSファイルを作成: C:/tmp/ルールフロー_v1_0.eds

なお、この動作結果からわかるように、precompileDecisionService()メソッドを使用してEDSファイルを作成すると、ファイル名は自動的に「<ディシジョン・サービス名>_v<ルールフローのバージョン>_<ルールフローのマイナーバージョン>.eds」になります。


copyEdsFile

<copyEdsFile>


	private static void copyEdsFile() {
		try {
			// ローカルのedsをネットワークドライブに割り当てたWindowsファイル共有サーバーにコピー。
			File[] files = new File(ERF_DIR).listFiles();
			for (File f : files) {
				if (f.getPath().endsWith(".eds") != true) continue;

				Path pathFrom = Paths.get(f.getPath());
				Path pathTo = Paths.get(WIN_NET_DRV + f.getName());
				Files.copy(pathFrom, pathTo, StandardCopyOption.REPLACE_EXISTING);
				System.out.println("Copy From: " + f.getPath() + 
						", To: " + WIN_NET_DRV + f.getName());
			}
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

copyEdsFileでは、ERF_DIR(ここではC:\tmp\)以下にある拡張子が.edsの全ファイルを、ネットワークドライブに割り当てたWindowsファイル共有サーバー(ここではY:\)以下にコピーしています。このプログラムに関しては、Corticon ServerのAPIとは一切関係なく、Java標準のファイル操作ライブラリを使用しているだけです。
EDSファイルをCorticon Serverが動作しているマシンにコピー(アップロード)するのに、他のプロトコル(HTTP, FTP, SCPなど)を使用したい場合は、それぞれに応じたプログラムに差し替えてください。

例えば、ERF_DIR(C:\tmp\)以下に「test_v1_0.eds」, 「ルールフロー_v1_0.eds」という2個のEDSファイルがあった場合、このcopyEdsFileの実行結果としては以下になります。

<copyEdsFile実行結果>


Copy From: C:\tmp\test_v1_0.eds, To: Y:/test_v1_0.eds
Copy From: C:\tmp\ルールフロー_v1_0.eds, To: Y:/ルールフロー_v1_0.eds

deployRemoteServer

<deployRemoteServer>


	private static void deployRemoteServer() {
		try {
			String response;

			File[] files = new File(ERF_DIR).listFiles();
			for (File f : files) {
				if (f.getPath().endsWith(".eds") != true) continue;

				String dsName = f.getName().split("_")[0];

				// デプロイ済みのディジョン・サービス一覧をチェックし、すでに存在していれば削除
				if (getDsNamesRPC().contains(dsName)) {
					response = CcMessageHandler.executeRPC(CCSERVER_URL,
							"removeDecisionService",
							new Object[] {dsName});
					System.out.println(dsName + " を削除: " + response);
				}

				// ディシジョン・サービスをデプロイ
				response = CcMessageHandler.executeRPC(CCSERVER_URL,
					"addDecisionService3",
					new Object[] {dsName, LINUX_MNT_DIR + f.getName(), false});
				System.out.println(dsName + " をデプロイ: " + response);
			}

			System.out.println("デプロイ済みディシジョン・サービス一覧: " + getDsNamesRPC());
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

このdeployRemoteServerは、前提として、Corticon Server (Tomcat)が動作しているLinuxサーバーで、EDSをコピーしたWindowsファイル共有サーバーがLinuxのディレクトリLINUX_MNT_DIR(ここでは/home/tani/fugafuga)にマウント済みになっていることを想定しています。注意点としては、LINUX_MNT_DIRディレクトリに、Corticon Server (Tomcat)の実行ユーザーの読み込み権限が必要です。また、もし他のプロトコルでLinuxサーバーにEDSファイルをアップロードした場合は、そのアップロードしたディレクトリに読み替えてください。

次に、このdeployRemoteServerでは、Corticon ServerのWeb APIにアクセスして、ディシジョン・サービスの削除とデプロイを行っています。
Corticon ServerのWeb APIの呼び出し方法としては大きく分けて以下の3種類の方法があります。

[Corticon ServerのWeb APIの呼び出し方法]

[Corticon ServerのWeb APIの呼び出し方法]の(1)に関しては、以下のURLにアクセスすると、SOAP内容を定義したWSDLを取得することができます。
https://<IPアドレス>:<ポート番号>/axis/services/CorticonAdmin?WSDL

<WebブラウザでWSDLを表示した画面(抜粋)>

画像3

このWSDLを使用すると、[Corticon ServerのWeb APIの呼び出し方法]の(1)である、Corticon ServerのWeb API を呼び出すSOAPクライアントの実装を行うことができます。しかし、この(1)の方法は、少し大げさで大変です。

そこで、Corticonでは、[Corticon ServerのWeb APIの呼び出し方法]の(2)として、より簡単にSOAP通信が行う方法が用意されています。具体的には、Web APIを呼び出すSOAPクライアントをラッピングしたCcMessageHandler.executeRPC()というメソッドが、あらかじめCorticon Serverのライブラリに用意されています。このサンプルプログラムdeployRemoteServerでも、そのCcMessageHandler.executeRPC()を使用しています。

CcMessageHandler.executeRPC()の使用方法としては、第一引数にCorticon ServerのURL文字列、第2引数に実行したいメソッド名、第3引数にそのメソッドへのオプション(Object型の配列)を指定します。CcMessageHandler.executeRPC()で実行可能なメソッド名やそのオプションの一覧は前述のWSDLに記載されています。CcMessageHandler.executeRPC()を実行すると、実際にはCorticon ServerとSOAP通信が行われ、指定したメソッドが実行されます。

このdeployRemoteServerでは、CcMessageHandler.executeRPC()で「removeDecisionService」というメソッドと「addDecisionService3」というメソッドを実行しています。

「removeDecisionService」は第1引数がディシジョン・サービス名です。実行すると指定されたディシジョン・サービスをCorticon Serverから削除します。

「addDecisionService3」は第1引数がディシジョン・サービス名, 第2引数がEDSファイルのパス文字列, 第3引数がEDSファイルの変更を監視するかどうかの真偽値です。実行すると指定されたEDSをディシジョン・サービスとしてデプロイします。
第1引数のディシジョン・サービス名は、EDSファイル名を「_」(アンダースコア)で分割し最初の要素を9行目で取得し、それをディシジョン・サービス名として指定しています。
また、第3引数は、EDSファイルの変更監視は特に必要ないので、falseを指定しています。EDSファイルの変更監視に関しては、製品マニュアル「インテグレーション& デプロイメントガイド」の「dynamicUpdateMonitor」に関して記載されている箇所をご確認ください。

なお、これらのWeb APIのメソッドを呼び出すと、実際には、Corticon Server本体のAPI (ICcServerインターフェース)の同名メソッドが直接実行されます。(addDecisionService3に関しては、ICcServerの引数3個版のaddDecisionService()と同等です。)したがって、Web APIの各メソッドのより詳細な仕様や引数に関しては、CorticonのJavaDoc内のICcServerに含まれる各同名メソッド説明を確認してください。

LINUX_MNT_DIR(ここでは/home/tani/fugafuga)にtest_v1_0.eds, ルールフロー_v1_0.edsという2個のEDSファイルがある前提で、このプログラムdeployRemoteServerを実行すると、以下のような結果になります。

<deployRemoteServer実行結果>


test をデプロイ: COMPLETE
ルールフロー をデプロイ: COMPLETE
デプロイ済みディシジョン・サービス一覧: test;ルールフロー

■ getDsNamesRPC

<getDsNamesRPC>


	private static String getDsNamesRPC() {
		String response = "";
		try {
			response = CcMessageHandler.executeRPC(CCSERVER_URL,
					"getDecisionServiceNames",
					new Object[] {});
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return response;
	}

このgetDsNameRPCでも、前述の[Corticon ServerのWeb APIの呼び出し方法](2)であるCcMessageHandler.executeRPC()を利用して、「getDecisionServiceNames」メソッドを実行しています。「getDecisionServiceNames」メソッドは、現在Corticon Serverにデプロイされているディシジョン・サービスの一覧を文字列で取得します。

ちなみに、この「getDecisionServiceNames」のような引数なしのシンプルなメソッドの場合、前述の[Corticon ServerのWeb APIの呼び出し方法]の(3)の方法も便利です。やり方は簡単ですので、ここで紹介だけさせてください。

例えば「getDecisionServiceNames」の場合、「http:/</IPアドレス>:<ポート番号>/axis/services/CorticonAdmin?method=getDecisionServiceNames」というURLにアクセスするだけです。WebブラウザでこのURLにアクセスすると、以下のような「getDecisionServiceNames」メソッドの実行結果が簡単に取得できます。URLの「?method=・・・」の部分を他のメソッド名に変えると他のメソッドを実行することもできます。

<Webブラウザで上記URLにアクセスした画面>

画像4

なお、余談ですが、この「getDecisionServiceNames」は、Corticon Serverが正常に稼働していれば必ず値を返すため、この「getDecisionServiceNames」を実行するURLは、例えばCorticon Serverの死活監視や起動確認にも利用できます。

まとめ

Corticon ServerのAPIを利用して、ディシジョン・サービスのデプロイプログラムを実装することの最大のメリットは、他の手法ではどうしても手作業が入る部分も、プログラマブルに全て自動化できるところです。例えば、今回の記事のプログラムに以下のような改良(機能追加)を行って、よりディシジョン・サービスの運用方針に則ったプログラムにすることも考えられます。

Corticon Serverの運用を行う際には、このようなディシジョン・サービスをデプロイするJavaプログラムを実装することも、選択肢の一つとして検討してみてはいかがでしょうか。

著者紹介

谷列樹さん

情報基盤技術統括部 プログレス推進部

以前は、Linux系のプログラマ兼SEとして、受託請負開発などに従事していた。
また、IT系雑誌や書籍の記事執筆などにも携わった経験をもつ。
現在は、BRMS Progress Corticonの技術サポート、研修などを行う。