2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

IBM Operational Decision Manager メモ - (2) ルール開発から実行までの流れ

Last updated at Posted at 2022-04-11

はじめに

ODMを使ってルールを開発してそれを利用する流れを確認するために、ここでは製品提供のチュートリアルをなぞっていきたいと思います。ただ指示に従って作業していくだけだと何をやっているのか見失いがちなので、各操作について整理しながら進めていきます。

関連記事

IBM Operational Decision Manager メモ - (1) 概要、Linuxへのインストール
IBM Operational Decision Manager メモ - (2) ルール開発から実行までの流れ
IBM Operational Decision Manager メモ - (3) Decision Center利用の流れ
IBM Operational Decision Manager メモ - (4) Linux上での環境セットアップ
IBM Operational Decision Manager メモ - (5) z/OS上での環境セットアップ
IBM Operational Decision Manager メモ - (6) z/OS上でのルール呼び出し
IBM Operational Decision Manager メモ - (7) zODM環境補足

チュートリアルのシナリオ概要

今回実行するチュートリアルは以下に提供されるMiniloanと呼ばれる簡素化されたローン審査のアプリケーションを使います。
Getting started with business rules
このアプリケーションはLiberty上で稼働するWebアプリケーションの形式で提供されています(Servletをベースに実装されている)。
image.png
上のような画面が提供されていて、借り手の情報とローン申請内容を入力して「Validate Loan」ボタンを押すと、入力した内容から特定の判断基準に基づいてローン受け入れ可否を判定して結果を表示します。

シナリオとしては、Javaで実装されているアプリケーションから、ビジネス・ルールに相当するローン審査部分、つまり、「借り手の情報とローン申請内容からローン引き受け可否を判定する部分」を抽出して、ODMで管理させるようにアプリケーションを変更する、というのが大きな流れとなります。

ただ、チュートリアルを簡単に進めるために、提供されているアプリケーションの構造としては以下のように、埋め込みのロジックでローン可否を判断するフローと、ODM上のルールを使用してローン可否を判断するフローの両方を選択できるような作りになっています。

image.png

最初はODM上に管理されるルールが無い状態なので、埋め込みロジックを使ったフローでのみアプリケーションを動かすことができます。
ルールを作成してODM上にデプロイすれば、Javaの埋め込みコードの代わりにODM上のルールを呼び出すフローでアプリケーションを動かせるようになる、という寸法です。
このようにルールを外出しにしてあげれば可視化されて管理しやすいし、頻繁にルールを変更したい場合にもアプリそのものに手を入れなくても柔軟に変更できますよ、というお話です。

さて、チュートリアルでやることの大枠をイメージしたところで、手順に従って具体的に進めていきましょう。

チュートリアル実施

Getting started with business rules

事前準備

と、その前に、チュートリアルを実施するには先の記事でWindows側にインストールしたコンポーネントだけでは足りなかったので、追加でWindows側にコンポーネントをインストールします。
(最初の手順でSample Consoleを起動することになるのですが、これインストールしてなかった...)
先のインストール手順と同様、Installation Mangerからインストールを行います。以下の画面で「サンプルおよびチュートリアル」をチェックします。
image.png
この時、依存関係のある以下のコンポーネントもインストールする必要があるようです。

  • Rule Executtion Server
  • Rule Execution Server for Liberty profile
  • Build Command

RESはLinuxのものを使う想定なのですが、なぜかその辺融通が効かないというか...。しょうがないので一緒に入れます。で、さらにLibertyも必要になるので、Libertyも事前にWindows上にインストールしておく必要があります(使わないんだけど...)。LibertyはODMのインストーラーに一緒に提供されている「wlp-base-embeddable-21.0.0.9.zip」を適当なディレクトリに展開しておけばよいだけです。
ここではc:\x\IBM\WebSphere\wlp-base-21.0.0.9_ODM811に配置しておきます。こんな感じ。
image.png
Javaも必要になります。まぁそこは適当に。

もう一つ、追加でサンプルをインストールする際にDesigner用に使用するeclipseにアクセスするっぽいのですが、その時に日本語環境で起動するようになっていると以下のようなエラーで失敗します。
image.png
なので、eclipse.iniを編集して英語モードで起動するようオプションを指定しておく必要がありました。
具体的にはeclipse.iniの先頭に-nl en_USを追加しておきます。

\x\eclipse\eclipse-jee-2020-06-R-ODM811\eclipse.ini
-nl en_US
-startup
plugins/org.eclipse.equinox.launcher_1.5.700.v20200207-2156.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.1200.v20200508-1552
-product
org.eclipse.epp.package.jee.product
-showsplash
org.eclipse.epp.package.common
--launcher.defaultAction
openFile
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
-Dosgi.requiredJavaVersion=1.8
-Dosgi.instance.area.default=@user.home/eclipse-workspace
-XX:+UseG1GC
-XX:+UseStringDeduplication
--add-modules=ALL-SYSTEM
-Dosgi.requiredJavaVersion=1.8
-Dosgi.dataAreaRequiresExplicitInit=true
-Xms256m
-Xmx2048m
--add-modules=ALL-SYSTEM

で、Installation Managerに戻って、インストール進めます。
Javaのパス指定
image.png
Libertyのパス指定
image.png
ライセンス情報指定
image.png

image.png

これで、Sample Consoleというのがインストールされたので、Windowsのスタートメニューから起動してみます。
image.png

image.png

Sample Consoleとは言っても実体としては英語モード、パースペクティブ指定でEclipse起動してるだけっぽいんですけどね...

Starting the Miniloan web application

先の記事でLinuxに立てたSample Serverを起動します。そこにMiniloanアプリがデプロイされているので、それをブラウザからアクセスして動かしてみます。

デフォルトで指定されている値はそのまま、「Validate Loan」をクリックします。
image.png
判定結果として「Rejected」が返されました。
概要で示したように、Javaコードとして埋め込まれた判定ロジックを使ったフローを動かしてみた、ということです。

Task 1: Designing the main rule project in the decision service

Step 1: Starting Rule Designer and importing the getting started projects

Sample Console(Rule Designer)を起動して、Getting Started - Decision Server - start - Import projectsを選択します。
image.png

サンプルのプロジェクトがインポートされて、Ruleパースペクティブが開きます。
image.png

Step 2: Creating the main rule project for the decision service

"Decision Service Map"という作業手順のガイドのようなものが用意されており、基本的にはこのガイドに沿って作業を進めていけばよいようになっているようです。
まずは、このDecision Service Mapの最初のメニュー"Create main rule project"をクリックします。
image.png

Main Rule Projectを選択してNext
image.png

プロジェクト名を指定してNext
image.png

Finish
image.png

これで枠となるプロジェクトが作成されます。

Step 3: Importing the XOM into your rule project

作成したプロジェクトに、XOM(Execution Object Model: "ゾム"と発音します)をインポートします。

補足: ルールを抽出して外出しにする場合、それは1つの"サービス"のように扱われます。すなわち判断基準の元となる情報を与えて(Input)、判断結果を受け取る(Output)ということになります。このInput/Outputとしてなんらかのデータをやりとりすることになりますが、そのデータ構造を表すものがXOMです。データ型を表すJava Bean(フィールドの定義とそれらをアクセスするgetter/setterメソッドが定義されたクラス)のようなものと捉えておけばよいと思います。今回はサンプルなので事前にJava用のXOMが提供されていますが、これはルールに対して受け渡しするデータに応じて作成することになります。
参考: Designing a BOM for a Java model

Decision Service Map の "Import XOM"をクリックします。
image.png

Java execution object modelを選択
image.png

miniloan-xomというJava XOMがサンプルとして提供されているので、それを選択します。
image.png

Java用のXOMがプロジェクトにインポートされました。
image.png

Step 4: Creating the business object model

ここでは、先にインポートしたXOMを元にしてBOM(Business Object Model: "ボム"と発音します)を作成していきます。

補足: ルールを作成する際にそのルールで扱われるデータ構造を表すオブジェクトがBOMです。XOMと位置づけが似ていますが、BOMはルール呼び出し元の言語(JavaやCOBOLなど)に依存しないODMの世界で管理されるオブジェクトです。アプリケーションが渡すデータはXOMを介してODM上のBOMにマッピングされるというイメージで捉えるのがよいと思います。BOM, XOMについては以下参照。
参考: Overview: BOM and execution object model (XOM)

Decision Service Map の "Create BOM"をクリックします。
image.png

名前を指定し、"Create a BOM entry from a XOM"を選択してNext
image.png

先ほどインポートしたXOMを選択し、Borrower, LoanにチェックしてNext
image.png

全てチェックしてFinish
image.png

XOMからBOMが生成されました。
image.png

生成されたBOMからLoanをダブルクリックし、さらにMembers以下のaddToMessages(String)をダブルクリックします。
image.png

Member VerbalizationのところにあるTemplatesを確認してみます。
image.png

ODMではルールを記述する際にプログラミング言語ではなく、自然言語のような文言を使用することができます。上の例は、LoanのaddToMessageというメソッドを使うのに、"add xxx to the messages of xxx"というような形式で記述できることを意味しています。これは後ほど実際のルールを記述する際に使われます。

Step 5: Defining a decision operation

ここではDecision Operationというものを定義していきます。

補足: Decision Operationというのはルールを呼び出す単位を示すものです。先にも記載したように、ODM上に抽出したルールは"サービス"のように扱われます。すなわち、入出力データとして何を使用し、どのようなロジックを実行するかを定義することになりますが、それを"Decision Operation"として定義します。SOAPなどのWebサービスでいう所のWSDLのOperationに相当する、と理解すると分かりやすいと思います。

Decision Service Mapから、"Add decision operation"をクリックします。
image.png

名前を指定してNext
image.png

プロジェクトを指定してFinish
image.png

deployment以下にDecision Operationの雛形が作成されます。
image.png

Decision Service Mapから"Go to operation map"をクリックします。
image.png

先ほど作成したDecision Operationを選択してOK
image.png

新たにOperation Mapという画面が開きます。
image.png

こういう階層のイメージです。
image.png

この後Decision Operationの中身を定義していくことになりますが、ここで実行するタスクがたくさんあるのでこのように別のMapでガイドが提供されています。

Step 6: Designing the operation signature

ここでは先に作成したオペレーションに対して入出力データを定義します。

Operation Mapから"Add variable set"をクリック
image.png

名前を指定してFinish
image.png

Addボタンを押します
image.png

1行追加されるので、Nameに"borrower"を指定し、Typeとしては"miniloan.Borrower"を選択します。
image.png

同様に、miniloan.Loanも追加して保存します。
image.png

Operation Mapから"Bind variablesをクリックします。
image.png

以下の矢印のように、先に追加したパラメータを、In/Out/In-Outのいずれかに割り当てます。ここでは、borrowerをInput Parametersの表にドラッグ&ドロップ、loanをInput-Output Parametersの表にドラッグ&ドロップします。
image.png

結果このようになります。
image.png

つまり、ルール呼び出しの際にborrowerとloanを渡して、結果としてloanを受け取るという定義をしていることになります。

ここまでの操作の整理

ここまでの作業イメージを図で表すとこんな感じです。
image.png

Task 2: Orchestrating the rules

ここから本丸である"ビジネス・ルール"をRule Designerを用いて実装していきます。つまりJavaでコーディングされていたローン可否判定ロジックを、ODM上で組み立てていくことになります。

ちなみにJavaで実装されていたコードを覗いてみるとこんな感じになっています。

参考: Javaによる判定ロジック
JavaClient.java
/*
* Copyright IBM Corp. 1987, 2021
* 
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
* 
**/
package com.ibm.odm.samples;

import java.text.MessageFormat;

import javax.json.Json;
import javax.json.JsonObject;

import miniloan.Borrower;
import miniloan.Loan;

public class JavaClient {
  // Java Validation Part
  public String validateWithJava(Loan loan, Borrower borrower) {
    checkMaximumAmount(loan, borrower);
    checkRepaymentAndScore(loan, borrower);
    checkMinimumIncome(loan, borrower);
    checkCreditScore(loan, borrower);
    JsonObject response;
    if (loan.isApproved()) {
      response = Json.createObjectBuilder()
          .add("decision",  "Your loan is approved with a yearly repayment of " + loan.getYearlyRepayment())
          .build();
    } else {
      response = Json.createObjectBuilder()
          .add("decision",  "Your loan is rejected")
          .add("messages",  loan.getMessages().toString())
          .build();
    }

    JsonObject value = Json.createObjectBuilder()
    .add("approved",loan.isApproved())
    .add("response", response)
    .build();

    return value.toString();

  }

  /**
   * check Repayment And Score
   */
  private void checkRepaymentAndScore(Loan loan, Borrower borrower) {
    if (borrower.getYearlyIncome() > 0) {
      int val = loan.getYearlyRepayment() * 100
          / borrower.getYearlyIncome();
      if ((val >= 0) && (val < 30) && (borrower.getCreditScore() >= 0)
          && (borrower.getCreditScore() < 200)) {
        loan.addToMessages(Messages
            .getString("debttoincometoohighcomparedtocreditscore"));
        loan.reject();
      }
      if ((val >= 30) && (val < 45) && (borrower.getCreditScore() >= 0)
          && (borrower.getCreditScore() < 400)) {
        loan.addToMessages(Messages
            .getString("debttoincometoohighcomparedtocreditscore"));
        loan.reject();
      }
      if ((val >= 45) && (val < 50) && (borrower.getCreditScore() >= 0)
          && (borrower.getCreditScore() < 600)) {
        loan.addToMessages(Messages
            .getString("debttoincometoohighcomparedtocreditscore"));
        loan.reject();
      }
      if ((val >= 50) && (borrower.getCreditScore() >= 0)
          && (borrower.getCreditScore() < 800)) {
        loan.addToMessages(Messages
            .getString("debttoincometoohighcomparedtocreditscore"));
        loan.reject();
      }
    }
  }

  /**
   * Check Minimum Income
   */
  private void checkMinimumIncome(Loan loan, Borrower borrower) {
    if (loan.getYearlyRepayment() > (borrower.getYearlyIncome() * 0.3d)) {
      loan.addToMessages(Messages.getString("toobigdebttoincomeratio"));
      loan.reject();
    }
  }

  /**
   * Check Credit Score
   */
  private void checkCreditScore(Loan loan, Borrower borrower) {
    if (borrower.getCreditScore() < 200) {
      loan.addToMessages(Messages.getString("creditscorebelow200"));
      loan.reject();
    }
  }

  /**
   * Check Maximum Amount
   */
  private void checkMaximumAmount(Loan loan, Borrower borrower) {
    if (loan.getAmount() > 1000000) {
      loan.addToMessages(Messages.getString("theloancannotexceed1000000"));
      loan.reject();
    }
  }


  
  protected static String escapeString(String str) {
    return str.replaceAll("\"", "\\\\\"").replaceAll("\n", "");
  }
  protected static String formatTrace(String ruleName, String taskName) {
    String format = Messages.getString("messagefiredinruletask");
    Object[] arguments = { ruleName, taskName };
    return MessageFormat.format(format, arguments);
  }


}

今回実装したいロジックでは、いくつかの条件の組み合わせでAccept or Rejectを判定する訳ですが、フローとしては大きく2種類の判断ロジックに分かれます。
(1) ローン額の上限値判定
(2) 借り手の情報(収入やクレジットスコアなど)とローン額の組み合わせから判定
以降の手順では(1)の部分を"Validation"、(2)の部分を"Eligibility"と名付けて各種オブジェクトを作成していくことになります。

大きな流れとしては、
(1)で絶対的なローン上限値を超えているかどうかの判定を行い、越えていればReject、越えていなければ(2)の判定に進む
(2)で各種情報をの組み合わせから詳細な条件判定を行う
という感じです。

Step 1: Creating rule packages

まずRule Packageというものを作ります。

補足: Rule Packageというのは、個々のビジネス・ルールを収める箱のようなものです。Javaでいう所の関連するクラスをまとめるPackageのようなものと理解すればよいでしょう。つまり関連性のある具体的なルールをまとめる単位ということになります。

ここでは先に示した2つの分類に従って、"validation", "eligibility"という2つのRule Packageを作成します。
Operation Mapから"Add rule package"をクリック。
image.png

Package名に"validation"を指定してFinish
image.png

同様に"eligibility"というRule Packageも作成します。
結果として以下の様に2つのパッケージが作成されます。
image.png

ここでは一旦パッケージだけ作っておき、実際のルールそのものの作成は後回しにします。

Step 2: Creating the ruleflow diagram

ここではRuleflowというものを作ります。

補足: 抽出したルールは1つの"サービス"のように扱われることになりますが、サービスとして動くメインのフローを定義するためのものが"Ruleflow"です。ローン可否判断をするにはいくつかのルール(条件判定)を組み合わせて最終的な判断を行うことになりますが、"Ruleflow"ではそれらのルールをどういう順番でどういう風に組み合わせるか、という大きな流れを定義することになります。

Operation Mapから"Add ruleflow"をクリック。
image.png

名前を指定してFinish
image.png

Ruleflowが作成されて、エディターが開きます(白紙状態)。
image.png

このエディター上で、グラフィカルにフローを作成することができます。
start/end それぞれのノードをドラッグ&ドロップします。
image.png

Step 3: Defining rule tasks

間にrule taskノードをドラッグ&ドロップします。
image.png

rule taskをクリックしてProperties viewにてIDを"validation"に変更しAlgorithm: Fastpathを選択します。
image.png

Properties viewのRule Selectionタブで、Editをクリック。
image.png

先に定義したvalidationパッケージを選択します。
image.png
これで、このノードにvalidationパッケージが紐づけされました。

同様に、eligibliltyというノードをエディター上に作成し、elibibilityパッケージを紐づけます。
image.png

各ノード間を以下のように矢印でつなぎます。
image.png

"Layout All Nodes"というアイコンをクリックするときれいに配置が整います。
image.png

Step 4: Defining the main transition

validation - eligibility間の矢印をクリックしてProperties viewにて、以下のように設定します。
image.png
これは、validationノードの結果として「'the loan' is approved」と判断された場合次のeligibilityノードに進む、ということを表しています(それ以外の場合はendノードに分岐)。

Step 5: Defining the final action

最後に、endノードをクリックして、Properties viewにて、以下の様な設定を行います。(ここでは最後に判定結果を出力させるステートメントを追記しています。)
image.png

ここまでで、先に示した全体のフローが定義できたことになります。
(1)validationでの判定
=> OKだったら(2)eligiblityでの判定
=> NGだったら終了
※validation, eligibilityの箇所で具体的にどのような判定を行うかというのはまだ実装していないので、後のステップで作っていくことになります。

Step 6: Binding the ruleflow

上で作成したRuleflowを、Task1で作成したDecision Operationに紐づけます。

補足: 繰り返しになりますが、抽出されたルールは"サービス"のように扱われることになり、その呼び出し単位はDecision Operationとして定義されます。Task1で作成したDecision Operation "my operation"には、入出力データの定義は行いましたが具体的に何のロジックを実行するか、という指定はしていませんでした。Task2では実行すべきメインのロジックであるRuleflowを作成したので、これをDecision Operation "my operation"に紐づけてあげます。

Operation Mapから"Bind ruleflow"をクリック。
image.png

Decision Operation Overviewの画面が開くので、Ruleflowの欄で"Use main ruleflow"を選択し、""のリンクをクリックします。
image.png

上で作ったRuleflowを選択してOK
image.png

保存します。
image.png

ここまでの操作の整理

Task2では、以下の(6)~(8)までを実施したイメージ。
image.png
ここまでで、どういうフローをどのように動かすかという大枠がやっとできた感じです。ここに個別の具体的な細かいルールを埋め込んでいく必要があります。その辺は次のTaskで...

Task 3: Authoring rules

ここでは具体的な判断ロジック(JavaやCOBOLでいうところのif文/case文相当のロジック)を作っていくことになります。

Step 1: Creating an action rule

先に作成したRule Package(valication/eligibility)以下に、action ruleというものを作っていきます。

補足: ここでは個別の判断ロジックを作っていくことになりますが、その記述方法には主に2種類の方法があります。
1つは"action rule"と呼ばれるオブジェクトを使う方法です。これはJavaやCOBOLのif文に近いイメージで実装する方法ですが、もう少し自然言語っぽく条件を記述することができます。比較的単純な判定を行う場合に適しています。
もう1つは"decision table"と呼ばれるオブジェクトを使う方法です。これは表のイメージで実装する方法で、複数のパラメーターの複雑な組み合わせで判定を行う場合に適しています。

Operation Mapから"Add action rule"をクリック。
image.png

まずvalidationパッケージにローン額の上限値の判定を行うための"maximum amount"というaction ruleを作成します。
Packageからvalidationを選択してNameに"maximum amount"を指定してFinish
※デフォルトではTypeとして"ActionRule"が指定されていますのでそのままにしておきます。
image.png

"maximum amount"というaction ruleが作成されてエディター(右側部分)が開きます。
image.png

Step 2: Completing the action rule

エディターの"Content"の欄に判定ロジックを記述していくことになります。
まず、ifと入力してpaceを押すとステートメント候補が表示されるのでそこから選択することができます(いわゆるコンテンツ・アシスト機能が使えます)。
image.png
image.png
image.png
image.png
image.png
コンテンツ・アシスト機能を使いながら以下のように記入していき、最後にセミコロンを記入します。
image.png
改行してCtrl+Spaceで候補を出し、reject <a loan>を選択
image.png
最後にセミコロンを記入。
image.png

Ctrl+Shift+Fで整形されます。
image.png

英語モードなのでちょっとありがたみが分かりにくいですが、このように自然言語っぽく条件が記述できます。
つまりここでは、「loanのamount(つまりローン額)が$1,000,000を超えていた場合、messagesに"The loan cannnot exceed 1,000,000"という文字列をセットして、Rejectつまり"不可"と判断する」というルールが定義できたことになります。

※これって実はCOBOL構文に近いんだよなぁ。元々COBOLは英語の構文に近い形で書けるように作られた言語なので...
サンプルは英語モードで実行する必要があるので英語モードにしてますが、日本語モードにすれば日本語での記述もできるはず。

validation部分のルールはこれで完了です。

Step 3: Importing remaining rules

次にeligiblility部分のルールを実装していきます。

ここは結構複雑なルールの組み合わせなので、ここでは一から作るのではなく事前に定義を作ってくれているものをインポートすることで代替します。

メニューからFile-Importを選択し、General-File Systemを選択してNext
image.png

From directoryで<InstallDir>/gettingstarted/DecisionServer/answer/Miniloan Serviceを選択
左側の画面でMiniloan Service-rules-eligilibityを選択し、右側のファイル一覧から.rulepackage以外をチェック
Into folderでmy decision serviceを選択
OptionsでOverwrite existing resources without warningにチェック
image.png

これで、eligibility関連のルールがインポートされました。
image.png

Step 4: Viewing the imported rules

eligibilityパッケージとしては以下の3つのルールが定義されています。

(1) minimum credit score (action rule)
image.png
(2) minimum income (action rule)
image.png
(3) repayment and score (decision table)
image.png

補足: (1)、(2)は記述内容を見ればまぁやってることは分かりやすいと思うので解説は省略します。decision tableとして記述されている(3)のルールについて補足します。これは、"debt to income"と"credit score"の組み合わせでローン可否判定をするための表です。"debt to income"は、借り手の年収における返済額の割合を示しています。"credit score"は入力されたcredit scoreの数値そのものです。例えば表の1行目に注目すると"debt to income"が0%~30%で、かつ、credit scoreが0~200の場合はReject(不可)と判断されます。このように表の形でルールを記述することで直感的にも分かりやすく、抜け漏れや重複のリスクも軽減されます。

先に作成したRuleflow "miniloan" を見てみます。
eligibilityのノードを選択してProperties viewのRule Selectionタブを確認すると、eligibilityパッケージ下にインポートされた3つのルールがリストされていることが確認できます。
image.png

補足: ここで、この3つのルールについてはそれぞれ独立性が担保されている、つまり相互に依存関係が無いということに注意してください。ローン可否判定の基本的なロジックとしては初期値としてはapproved=true(許可)となっていて、いずれかのReject条件に合致した場合にステータスが上書きされる(approved=false)、というやり方でルールを実装しています。そのためこれら複数のルールの順序性は関係無く実行できることになります。
デフォルトではRuleflow中のノードの実行アルゴリズムは"Fastpath"になっています。
image.png
これは今回のルールのようにお互い干渉しない前提のルールの場合には利用可能ですが、例えばrule1のロジックで変更した値をベースにrule2のロジックで別の判断を行う、といった場合には意図した結果にならない場合があります。そのような場合、別のアルゴリズムを選択する必要がありますのでご注意ください。詳細は以下の辺りも参考に...
参考: Engine execution modes

ここまでの操作の整理

Task3では、以下の(9)~(10)までを実施したイメージ。
image.png
※青字はDecision Service Map, Operation Map のメニューにある操作

これで一通りルールの実装は完了です。

Task 4: Testing and debugging

ここでは、作成したルールをRule Designer上でテスト/デバッグしてみます。

Step 1: Creating a run configuration

EclipseのメニューからRun - Run Configurations... を選択
image.png

Decision Operationを右クリックしてNew Configurationを選択
image.png

適当な名前をつけて、テストするDecision Operationを選択します。
image.png

Parameters & Argumentsタブでルールのテスト時に与えるパラメーターを設定します。
表のborrowerを選択してEdit Valueをクリック
image.png

Expression valueを選択し、new miniloan.Borrower("Joe", 600, 8000)を入力してOK
image.png

同様にloanについてもEdit Valueを行い、new miniloan.Loan(50000, 240, 0.05)を指定します。
最終的には以下のようになるので、ApplyをしてRun。
image.png

すると、指定した値を元にルールが動いて結果がConsoleに返されました。
image.png

Step 2: Inserting a breakpoint

Ruleflowを開いてeligibilityノードを右クリックし、Toggle Breakpointを選択
image.png

ブレークポイントが設定されたことを示す、丸印が表示されます。
image.png

もう一つ、eligibilityパッケージに含まれるminimum incomeというruleを開き、Contentの4行目の左端の空白部分を右クリックしToggle Breakpointを選択
image.png

ブレークポイントが設定されたことを示す、丸印が表示されます。
image.png

Step 3: Running the debugger

今度はデバッグモードでテスト実行します。

EclipseのメニューからRun - Debug Configurations...を選択
image.png

上で作ったMiniloan Testを選択してDebug
image.png

以下のポップアップが出るのでSwitchをクリックしてDebugパースペクティブに切り替えます。
image.png

ブレークポイントで処理がストップして状況を確認できるようになります。
image.png

あとはJavaアプリなどと同じように次のブレークポイントまで進めたり、変数の値を確認したりできます。
image.png
image.png
最後まで進めると先ほどのテストと同じように結果がConsoleに表示されます。
image.png

ここまでの操作の整理

Task4では、以下の(11)~(12)までを実施したイメージ。
image.png
※青字はDecision Service Map, Operation Map のメニューにある操作

Task 5: Deploying and running your ruleset

Rule Designer上でルールの作成、テストまで済んだので、次はこれを実際の稼働環境であるRES(Rule Execution Server)にデプロイして動かしてみます。

事前確認

もう一度MiniloanのWebアプリにアクセスします。ここでは一応Use rulesにチェックを入れてODM上のルールを使うフローを動かしてみます。
image.png
まだルールをRES上にデプロイしていないので、そんなの無いよってエラーになっています。このエラーは想定内。

Step 1: Creating a deployment configuration

Rule Designer上で"Deployment Configuration"というものを作成し、デプロイを行うための構成を行います(どのRESに何をデプロイするか、というのを設定していきます)。
Decision Service Mapから"Create deployment configuration"をクリック。
image.png

フォルダと名前を指定してFinish
image.png

Deployment configurationのガラが作成され、エディターが開きます。
image.png

Decision Operationsタブで、Configured Decision Operationsの下の「+」ボタンをクリック。
image.png

デプロイ対象のDecision OperationをチェックしてFinish
image.png

登録されました。
image.png

Step 2: Enabling ruleset monitoring

監視用のパラメーターを設定します。

追加したDecision Operatorを選択し、Ruleset Properties欄の「+」ボタンをクリック。
image.png

Name: ruleset.bom.enabled, Value: trueをセット
image.png

同様に、monitoring.enabled、ruleset.sequential.trace.enabled を追加し、いずれもtrueをセットします。
結果こんな感じになります。
image.png

Step 3: Deploying the ruleset

Ruleset Version Policy欄で、Increment minor version numbersを選択
image.png

Target Serversタブで「+」ボタンクリック
image.png

Create a Rule Executeion Server connectionを選択してNext
image.png

デプロイ先のRESの情報を指定
image.png

Test Connectionボタンをクリックして、接続が成功することを確認し、Finish
image.png

ターゲットのRES情報が登録されました。
image.png

設定を保存し、OverviewタブのProceed to RuleApp deploymentのリンクをクリックします。
image.png

オペレーションとターゲットを確認し、Next
image.png

認証情報を確認し、Next
image.png

Summary情報を確認し、Finish
image.png

デプロイ処理が行われ、結果が表示されます。
image.png

Step 4: Viewing the deployed RuleApp

きちんとデプロイされたかどうか、RES側を覗いて確認してみます。

ブラウザからRESコンソールにアクセスします。
image.png

エクスプローラータブから、my_operationが使用可能になっていることが確認できました。プロパティーも正しく設定されています。
image.png

Step 5: Testing the HTDS description file

RES上のRuleAppを簡易的にテストできる機能がRES Consoleから使えるようなのでテストしてみます。
対象のルールセットを開いて、"HTDS記述ファイルの取得"をクリック
image.png

プロトコル・タイプ: REST、フォーマット:OpenAPI-JSON を選択し、テストをクリック
image.png

以下のような画面になるので、入力データをJSON形式で指定して"要求の実行"をクリック
image.png

すると、以下の様に判定結果が返されました。
image.png

RES上でルールの単体テストが実施できました。

Step 6: Running the Miniloan web application with rules

それでは、いよいよ最終目的であるminiloanのWebアプリから、先ほどデプロイしたRES上のルール呼び出しを実行してみます。

ブラウザからminiloanのWebアプリにアクセスし、Use rulesにチェックを入れ、RESの接続情報を設定して"Validate Loan"実行!
すると今度はきちんとRES上のルールが実行されてその結果が画面に返されました!!!
image.png

これでルールの外出しが完了しました!

ちなみにWebアプリケーション(Java)からRES上のルール呼び出しは、REST(HTTP/JSON)でアクセスするコードに置き換わることになります。

参考: ルール呼び出し部分の実装
RESTJSONjavaClient.java
/*
* Copyright IBM Corp. 1987, 2021
* 
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
* 
**/

package com.ibm.odm.samples;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class RESTJSONJavaClient {

  /**
   * Get a closeable HTTP client
   * 
   * @return closeable HTTP client
   * @throws Exception
   */
  public static synchronized CloseableHttpClient getClient() throws Exception {
    CloseableHttpClient client = HttpClients.createDefault();
    return client;
  }

  /*
   * Return credentials for user id and password
   */
  private static String getBase64Credentials(String userId,String userPassword)
  {
    String authstring = userId + ":" + userPassword;
    String encoded = Base64.encodeBase64String(authstring.getBytes());
    return encoded;
  }

  /**
   * Execute a ruleset with the supplied payload to a specified endpoint URI using the 
   * supplied user id and password for authentication.
   * 
   * @param endpointURI
   * @param userId
   * @param userPassword
   * @param payload
   * @return ruleset execution response as String
   * @throws Exception
   */
  public static String executeRulesetWithJSONPayload(String endpointURI, String userId,
      String userPassword, String payload) throws Exception {
    String result = "";
    String errorMessage = "An error occurred when invoking the decision service at "
        + endpointURI
        + ":\n";
    HttpPost httpPost = null;

    CloseableHttpClient client = getClient();
    try {
      try {
        httpPost = new HttpPost(endpointURI);
      } catch (Exception e) {
        throw new RuntimeException(errorMessage 
            + e.getClass().getName() + ": " + e.getMessage());
      }
      // Authorization header required when accessing from internet
      String encodedValue = getBase64Credentials(userId, userPassword);
      String authorization = "Basic " + encodedValue;
      httpPost.addHeader("Authorization", authorization);

      // Add content type to header
      httpPost.addHeader("Content-Type", "application/json");

      CloseableHttpResponse response = null;

      try {
        // Set entity to payload for execution
        httpPost.setEntity(new StringEntity(payload));
        // Execute Post method using the HTTP client and retrieve response
        try {
          response = client.execute(httpPost);
        } catch (Exception e) {
          throw new RuntimeException(errorMessage
              + e.getClass().getName() + ": " + e.getMessage());
        }

        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
          int statusCode = response.getStatusLine().getStatusCode();
          System.err.println("Status Code: " + statusCode);
          System.err.println("Status Line: " + response.getStatusLine());
          String responseEntity = EntityUtils.toString(response.getEntity());
          System.err.println("Response Entity: " + responseEntity);
          if (statusCode == 302) {
            throw new RuntimeException(errorMessage
                + "Unauthorized. Check your user ID and password.");
          }
          else {
            throw new RuntimeException(errorMessage
                + response.getStatusLine() + ": " + responseEntity);
          }
        } else {
          result = EntityUtils.toString(response.getEntity());
          System.out.println("Result: " + result);
        }
      } finally {
        if (response != null) {
          response.close();
        }
      }
    } finally {
      client.close();
    }

    return result;
  }

}

ここまでの操作の整理

Task5では、以下の(13)~(16)までを実施したイメージ。
image.png
※青字はDecision Service Map, Operation Map のメニューにある操作

Task 6: Monitoring

ここまでで一通りルールを外出しにする手順は確認できましたが、ODMを使うと実行されたルールの稼働状況も簡単にモニターできるようなので見てみます。

Step 1: Running Rule Execution Server diagnostics

前の手順で実施済みなので割愛

Step 2: Viewing statistics on deployed RuleApps

RESコンソールのExplorerから対象のオペレーションを選択し、"統計情報の表示"をクリック
image.png

このルールが実行された回数、平均処理時間などの情報が確認できます。
image.png

Step 3: Searching for past transactions in Decision Warehouse

意思決定ウェアハウスタブを選択し、そのまま検索をクリック
image.png
※検索条件指定していないので全検索になります。まだほとんどルール実行していないのでこれでもよいですが、必要に応じて条件を絞り込めます。

ルール実行のインスタンスが一覧表示されます。
image.png

Step 4: Viewing the run rules

一覧表示された表から意思決定トレース列のリンクをクリックすると詳細が確認できます。
image.png

1つ目の例
image.png

2つ目の例
image.png

各ルール実行がどういうフローを辿って判断されたかというのが、このように確認できます。

Task 7: Publishing to Decision Center

ここまでは、Windows上のRule Designer(Eclipse)上でルールを開発してそれを実行環境であるRESにデプロイして動かすという流れをやってみました。一度このようにルールを作成すると、Decision Centerでルールを管理/メンテナンスすることができます。作成したルールをDecision Centerで管理するようにしておくと、ブラウザのインターフェースを使ってルールのメンテナンスが行えるため、開発者ではない業務よりのユーザーでもルールの変更/リリースのような操作が容易に行えるようになります。
ここでは、上で作成したルールをDecision Centerに公開するところをやってみます。

Step 1: Publishing the rule project to Decision Center

Linux上のSample Server(RESとDecision Center兼用)が上がっていて、ブラウザからDecision Centerにアクセスできることを確認しておきます。

image.png

image.png

Rule Designerで、Rule Explorer viewから対象のプロジェクトを右クリック - Decision Centerを選択
image.png

Decision Centerへの接続情報を設定
image.png

Connetボタンを押して接続が正常に行えることを確認します。OKであればNext。
image.png

Use Decision Governance FrameworkにチェックをしてFinixh
image.png

YesをクリックしてTeam Synchronizingパースペクティブを開きます。
image.png

Decision Centerにプロジェクトが公開され、Decision Centerとの同期を管理する画面が開きます。
image.png

これでDecision Centerへの公開は完了です。

Step 2: Exploring the rule project in Decision Center

ブラウザからDecision Centerにアクセスして公開したプロジェクトを確認してみます。
Decision Centerにログインしてライブラリータブを見ると、先ほど公開した"my decision service"が表示されています。
image.png

メインをクリック
image.png

意思決定成果物タブで"すべてのプロジェクト"をクリックし、"すべてのタイプ"にチェックを入れて適用します。
image.png

すべてのタイプのオブジェクトが表示されるので、validation - maximum amount を選択します。
image.png

action rule の中身を確認することができます。(編集も可)
image.png

前に戻ってeligibility - repayment and score を選択します。
image.png

decision table の中身を確認することができます。(編集も可)
image.png

このように、ブラウザのUIを使ってルールのメンテナンスなどを行うことができます。
※Decision Centerについては別のチュートリアルがあるのでそちらを実施する予定

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?