No.25 Corticon ServerのAPIを利用してディシジョン・サービスをバッチデプロイする
2018.01.31 Progress Corticon
本エントリーは株式会社アシスト様が寄稿したエントリー(https://www.ashisuto.co.jp/product/category/brms/progress_corticon/column/detail/brmstech25.html)を転載したものとなります。
Corticon Studioで作成したルールアセット(語彙ファイル、ルールシートファイル、ルールフローファイルの一式)を、ディシジョン・サービスとして利用するには、これらのファイルをプリコンパイル(※)したファイル(EDS)を作成し、Corticon Serverにデプロイしなければなりません。
Corticon Serverへルールアセットのデプロイは主に次の方法が用意されています。
- ●Corticon Studioの「デシジョンサービスのパッケージとデプロイ」機能でプリコンパイルおよびデプロイする。
- ●プリコンパイル済みのファイル(EDS)をWeb Consoleでデプロイする。
- ●プリコンパイル済みのファイル(EDS)をDeployment Consoleで作成しCDDでデプロイする。
これらの方法の詳細に関しましては、製品に付属しているマニュアルにそれぞれ詳細が記載されています。それぞれの方法を組み合わせることもできますので、運用場面によって、柔軟にディシジョン・サービスのデプロイ手順を検討することができるようになっています。しかし、上記に挙げた方法は、運用方針として統制がとりにくかったり、手作業が必要なステップがあったり、どれも一長一短があります。
そこで、今回の記事では、Corticon ServerのAPIを利用してディシジョン・サービスをデプロイする方法を紹介します。Javaプログラムの実装が必要ですが、この方法であれば、ディシジョン・サービスのデプロイ作業の完全な自動化が可能です。
- ※このプリコンパイルとは、通常のプログラム言語等のプリコンパイルとは異なり、ルールアセットを元ににデプロイするための特殊なファイル(ファイル)を作成するという意味です。製品内ではその作業のことをプリコンパイルという用語で統一していますので、本記事内でもプリコンパイルと記述します。
[記事執筆環境]
Corticon 5.6.1
ディシジョン・サービスのデプロイプログラムの要件
ディシジョン・サービスをCorticon Serverにデプロイするプログラムの要件としては、以下を想定しています。
- 1.Corticon StudioをインストールしたWindows端末とCorticon ServerをインストールしたLinuxサーバーがある。
- 2.Windows端末とLinuxサーバーのファイル受け渡しはWindowsファイル共有サーバー経由で行う。
事前にWindows端末側ではネットワークドライブに割当を行い、Linuxサーバー側ではCIFSマウントを行う。 - 3.ディシジョン・サービスのデプロイプログラムは、Corticon Studioを導入したWindows端末で動作させる。
- 4.デプロイプログラムはCorticon Serverのライブラリに含まれるAPIを直接使用し、ルールアセットのプリコンパイル
(EDSファイルの作成)を行う。 - 5.デプロイプログラムは作成したEDSファイルをWindowsファイル共有サーバーにコピーする。
- 6.デプロイプログラムはCorticon ServerのWeb APIにアクセスし、Windowsファイル共有サーバーのEDSファイルを
ディシジョン・サービスとしてデプロイする。
この要件を図で表現すると以下になります。
この要件を実現する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で参照ライブラリーの追加の設定を行うと、以下のような画面になります。
<参照ライブラリー追加後の画面>
また、このプログラムを実行するには、JDKのlibに含まれているtools.jarが必要です。プログラム実行環境のJREには、JDKのtools.jarをコピーしてJRE\lib\ext\ 以下に配置してください。
プログラムをJARにエクスポートするかEclipseのテスト実行機能で実行すると、以下のような動作を行います。
- 1.Corticon Serverのライブラリに含まれているAPIを直接使用して、C:\tmp 以下にある全erfファイルをプリコンパイル
し、EDSファイルを作成する。 - 2.C:\tmp 以下にある全EDSファイルを、ネットワークドライブに割り当てたファイル共有サーバー(Y:\)にコピーする。
- 3.LinuxマシンのCorticon Server (ここではhttps://nnn.nnn.nnn.nnn:8080/axis/)のWeb APIにアクセスして、
ファイル共有サーバーをマウントしたディレクトリ(/home/tani/fugafufa)にある全EDSファイルをディシジョン・サービスとしてデプロイする。
以下で、プログラム内容の詳細な解説を行います。
プログラム内容の解説
■ 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の呼び出し方法]
- 1.実行したい内容を正確に記述したXMLをCorticon ServerにPOSTするプログラム(SOAPクライアント)を実装する
- 2.上記手続きを簡略化したCcMessageHandler.executeRPC()を使用するプログラムを実装する
- 3.所定のURLに直接アクセスする
[Corticon ServerのWeb APIの呼び出し方法]の(1)に関しては、以下のURLにアクセスすると、SOAP内容を定義したWSDLを取得することができます。
https://<IPアドレス>:<ポート番号>/axis/services/CorticonAdmin?WSDL
<WebブラウザでWSDLを表示した画面(抜粋)>
この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にアクセスした画面>
なお、余談ですが、この「getDecisionServiceNames」は、Corticon Serverが正常に稼働していれば必ず値を返すため、この「getDecisionServiceNames」を実行するURLは、例えばCorticon Serverの死活監視や起動確認にも利用できます。
まとめ
Corticon ServerのAPIを利用して、ディシジョン・サービスのデプロイプログラムを実装することの最大のメリットは、他の手法ではどうしても手作業が入る部分も、プログラマブルに全て自動化できるところです。例えば、今回の記事のプログラムに以下のような改良(機能追加)を行って、よりディシジョン・サービスの運用方針に則ったプログラムにすることも考えられます。
- プリコンパイル時やデプロイ時により細やかな制御を行う。例えばルールのバージョンが高いときだけ処理する、
など。 - より細やかなエラー制御を行う。例えばエラーが発生したら適切なタイミングでプログラムを停止し復旧できるように
する、など。 - より細やかなファイル制御を行う。例えばEDSを作成する前に前回のEDSのバックアップを取る、など。
- その他、複数のCorticon Serverへ同じEDSをデプロイできるようにする、など。
Corticon Serverの運用を行う際には、このようなディシジョン・サービスをデプロイするJavaプログラムを実装することも、選択肢の一つとして検討してみてはいかがでしょうか。
著者紹介
情報基盤技術統括部 プログレス推進部 |